tas-uell-sdk 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +122 -229
- package/esm2020/lib/components/tas-btn/tas-btn.component.mjs +79 -95
- package/esm2020/lib/components/tas-floating-call/tas-floating-call.component.mjs +74 -24
- package/esm2020/lib/components/tas-videocall/tas-videocall.component.mjs +50 -45
- package/esm2020/lib/components/tas-waiting-room/tas-waiting-room.component.mjs +179 -0
- package/esm2020/lib/config/tas.config.mjs +10 -0
- package/esm2020/lib/interfaces/tas.interfaces.mjs +32 -2
- package/esm2020/lib/services/tas.service.mjs +27 -48
- package/esm2020/lib/tas-uell-sdk.module.mjs +82 -0
- package/esm2020/public-api.mjs +13 -12
- package/esm2020/tas-uell-sdk.mjs +1 -1
- package/fesm2015/tas-uell-sdk.mjs +440 -218
- package/fesm2015/tas-uell-sdk.mjs.map +1 -1
- package/fesm2020/tas-uell-sdk.mjs +437 -216
- package/fesm2020/tas-uell-sdk.mjs.map +1 -1
- package/lib/components/tas-btn/tas-btn.component.d.ts +15 -11
- package/lib/components/tas-floating-call/tas-floating-call.component.d.ts +3 -2
- package/lib/components/tas-videocall/tas-videocall.component.d.ts +4 -3
- package/lib/components/tas-waiting-room/tas-waiting-room.component.d.ts +56 -0
- package/lib/config/tas.config.d.ts +28 -0
- package/lib/interfaces/tas.interfaces.d.ts +41 -6
- package/lib/services/tas.service.d.ts +6 -16
- package/lib/tas-uell-sdk.module.d.ts +46 -0
- package/package.json +34 -23
- package/public-api.d.ts +8 -7
- package/esm2020/lib/tas.config.mjs +0 -14
- package/esm2020/lib/tas.module.mjs +0 -73
- package/lib/tas.config.d.ts +0 -51
- package/lib/tas.module.d.ts +0 -34
|
@@ -1,27 +1,40 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, Injectable,
|
|
3
|
-
import * as i3 from '@angular/common';
|
|
4
|
-
import { CommonModule } from '@angular/common';
|
|
5
|
-
import * as i1 from '@ng-bootstrap/ng-bootstrap';
|
|
6
|
-
import { NgbModalModule } from '@ng-bootstrap/ng-bootstrap';
|
|
2
|
+
import { InjectionToken, Injectable, Inject, Component, Input, ViewChild, NgModule } from '@angular/core';
|
|
7
3
|
import { BehaviorSubject, Subscription } from 'rxjs';
|
|
8
4
|
import { map, catchError, switchMap } from 'rxjs/operators';
|
|
9
5
|
import * as OT from '@opentok/client';
|
|
10
6
|
import interact from 'interactjs';
|
|
7
|
+
import * as i1 from '@ng-bootstrap/ng-bootstrap';
|
|
8
|
+
import * as i3 from '@angular/common';
|
|
9
|
+
import { CommonModule } from '@angular/common';
|
|
11
10
|
|
|
12
11
|
/**
|
|
13
12
|
* Injection token for TAS configuration
|
|
14
13
|
*/
|
|
15
|
-
const TAS_CONFIG = new InjectionToken(
|
|
16
|
-
/**
|
|
17
|
-
* Injection token for HTTP client
|
|
18
|
-
*/
|
|
19
|
-
const TAS_HTTP_CLIENT = new InjectionToken("TAS_HTTP_CLIENT");
|
|
14
|
+
const TAS_CONFIG = new InjectionToken('TAS_CONFIG');
|
|
20
15
|
/**
|
|
21
|
-
* Injection token for
|
|
16
|
+
* Injection token for HTTP client adapter
|
|
22
17
|
*/
|
|
23
|
-
const
|
|
18
|
+
const TAS_HTTP_CLIENT = new InjectionToken('TAS_HTTP_CLIENT');
|
|
24
19
|
|
|
20
|
+
var TasRoomType;
|
|
21
|
+
(function (TasRoomType) {
|
|
22
|
+
TasRoomType["TAS"] = "TAS";
|
|
23
|
+
TasRoomType["JM"] = "JM";
|
|
24
|
+
TasRoomType["WEBINAR"] = "WEBINAR";
|
|
25
|
+
})(TasRoomType || (TasRoomType = {}));
|
|
26
|
+
var TasSessionType;
|
|
27
|
+
(function (TasSessionType) {
|
|
28
|
+
TasSessionType["SPONTANEOUS"] = "SPONTANEOUS";
|
|
29
|
+
TasSessionType["SCHEDULED"] = "SCHEDULED";
|
|
30
|
+
})(TasSessionType || (TasSessionType = {}));
|
|
31
|
+
var TasUserRole;
|
|
32
|
+
(function (TasUserRole) {
|
|
33
|
+
TasUserRole["OWNER"] = "OWNER";
|
|
34
|
+
TasUserRole["USER"] = "USER";
|
|
35
|
+
TasUserRole["MODERATOR"] = "MODERATOR";
|
|
36
|
+
})(TasUserRole || (TasUserRole = {}));
|
|
37
|
+
// Enums for TAS Service state management
|
|
25
38
|
var CallState;
|
|
26
39
|
(function (CallState) {
|
|
27
40
|
CallState["IDLE"] = "IDLE";
|
|
@@ -35,10 +48,11 @@ var ViewMode;
|
|
|
35
48
|
ViewMode["FULLSCREEN"] = "FULLSCREEN";
|
|
36
49
|
ViewMode["PIP"] = "PIP";
|
|
37
50
|
})(ViewMode || (ViewMode = {}));
|
|
51
|
+
|
|
38
52
|
class TasService {
|
|
39
|
-
constructor(
|
|
40
|
-
this.config = config;
|
|
53
|
+
constructor(httpClient, config) {
|
|
41
54
|
this.httpClient = httpClient;
|
|
55
|
+
this.config = config;
|
|
42
56
|
this.session = null;
|
|
43
57
|
this.publisher = null;
|
|
44
58
|
this.subscribers = [];
|
|
@@ -51,9 +65,6 @@ class TasService {
|
|
|
51
65
|
// Session info for PiP mode restoration
|
|
52
66
|
this.currentSessionId = null;
|
|
53
67
|
this.currentToken = null;
|
|
54
|
-
if (!this.config || !this.httpClient) {
|
|
55
|
-
console.warn("TasService: Configuration not provided. Make sure to use TasModule.forRoot()");
|
|
56
|
-
}
|
|
57
68
|
}
|
|
58
69
|
// Getters
|
|
59
70
|
get currentSession() {
|
|
@@ -91,7 +102,14 @@ class TasService {
|
|
|
91
102
|
toggleMute() {
|
|
92
103
|
if (this.publisher) {
|
|
93
104
|
const newMuteState = !this.isMutedSubject.getValue();
|
|
94
|
-
|
|
105
|
+
const shouldEnableAudio = !newMuteState;
|
|
106
|
+
// Use OpenTok's publishAudio
|
|
107
|
+
this.publisher.publishAudio(shouldEnableAudio);
|
|
108
|
+
// Also directly control the MediaStreamTrack as backup
|
|
109
|
+
const audioTrack = this.publisher.getAudioSource?.();
|
|
110
|
+
if (audioTrack) {
|
|
111
|
+
audioTrack.enabled = shouldEnableAudio;
|
|
112
|
+
}
|
|
95
113
|
this.isMutedSubject.next(newMuteState);
|
|
96
114
|
}
|
|
97
115
|
}
|
|
@@ -111,7 +129,7 @@ class TasService {
|
|
|
111
129
|
this.subscribers = [];
|
|
112
130
|
this.currentSessionId = null;
|
|
113
131
|
this.currentToken = null;
|
|
114
|
-
this.isMutedSubject.next(false);
|
|
132
|
+
this.isMutedSubject.next(false); // Reset mute state
|
|
115
133
|
this.viewModeSubject.next(ViewMode.FULLSCREEN);
|
|
116
134
|
this.callStateSubject.next(CallState.DISCONNECTED);
|
|
117
135
|
}
|
|
@@ -120,21 +138,13 @@ class TasService {
|
|
|
120
138
|
}
|
|
121
139
|
// API Methods
|
|
122
140
|
createRoom(payload) {
|
|
123
|
-
|
|
124
|
-
throw new Error("TasService not configured. Use TasModule.forRoot()");
|
|
125
|
-
}
|
|
126
|
-
const url = `${this.config.apiBaseUrl}/v2/room`;
|
|
127
|
-
return this.httpClient.post(url, payload).pipe(map((response) => response), catchError((error) => {
|
|
141
|
+
return this.httpClient.post("v2/room", { body: payload, headers: {} }).pipe(map((response) => response), catchError((error) => {
|
|
128
142
|
console.error("TAS Service: createRoom failed", error);
|
|
129
143
|
throw error;
|
|
130
144
|
}));
|
|
131
145
|
}
|
|
132
146
|
generateToken(payload) {
|
|
133
|
-
|
|
134
|
-
throw new Error("TasService not configured. Use TasModule.forRoot()");
|
|
135
|
-
}
|
|
136
|
-
const url = `${this.config.apiBaseUrl}/v2/room/token`;
|
|
137
|
-
return this.httpClient.post(url, payload).pipe(map((response) => response), catchError((error) => {
|
|
147
|
+
return this.httpClient.post("v2/room/token", { body: payload, headers: {} }).pipe(map((response) => response), catchError((error) => {
|
|
138
148
|
console.error("TAS Service: generateToken failed", error);
|
|
139
149
|
throw error;
|
|
140
150
|
}));
|
|
@@ -147,11 +157,6 @@ class TasService {
|
|
|
147
157
|
this.currentSessionId = sessionId;
|
|
148
158
|
this.currentToken = token;
|
|
149
159
|
return new Promise((resolve, reject) => {
|
|
150
|
-
if (!this.config) {
|
|
151
|
-
this.callStateSubject.next(CallState.ERROR);
|
|
152
|
-
reject(new Error("TasService not configured. Use TasModule.forRoot()"));
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
160
|
if (!OT.checkSystemRequirements()) {
|
|
156
161
|
this.callStateSubject.next(CallState.ERROR);
|
|
157
162
|
reject(new Error("Browser not compatible with TokBox"));
|
|
@@ -260,25 +265,23 @@ class TasService {
|
|
|
260
265
|
* Moves videos back to fullscreen containers
|
|
261
266
|
*/
|
|
262
267
|
moveVideosToFullscreen() {
|
|
263
|
-
this.moveSubscribersTo(
|
|
264
|
-
this.movePublisherTo(
|
|
268
|
+
this.moveSubscribersTo('subscriber-container');
|
|
269
|
+
this.movePublisherTo('publisher-container');
|
|
265
270
|
}
|
|
266
271
|
}
|
|
267
|
-
TasService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TasService, deps: [{ token:
|
|
272
|
+
TasService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TasService, deps: [{ token: TAS_HTTP_CLIENT }, { token: TAS_CONFIG }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
268
273
|
TasService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TasService, providedIn: "root" });
|
|
269
274
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TasService, decorators: [{
|
|
270
275
|
type: Injectable,
|
|
271
|
-
args: [{
|
|
276
|
+
args: [{
|
|
277
|
+
providedIn: "root",
|
|
278
|
+
}]
|
|
272
279
|
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
|
|
273
|
-
type: Optional
|
|
274
|
-
}, {
|
|
275
280
|
type: Inject,
|
|
276
|
-
args: [
|
|
281
|
+
args: [TAS_HTTP_CLIENT]
|
|
277
282
|
}] }, { type: undefined, decorators: [{
|
|
278
|
-
type: Optional
|
|
279
|
-
}, {
|
|
280
283
|
type: Inject,
|
|
281
|
-
args: [
|
|
284
|
+
args: [TAS_CONFIG]
|
|
282
285
|
}] }]; } });
|
|
283
286
|
|
|
284
287
|
class TasVideocallComponent {
|
|
@@ -300,10 +303,11 @@ class TasVideocallComponent {
|
|
|
300
303
|
}
|
|
301
304
|
ngOnDestroy() {
|
|
302
305
|
this.subscriptions.unsubscribe();
|
|
306
|
+
// Only disconnect if not in PiP mode (keep session alive for floating window)
|
|
303
307
|
if (!this.tasService.isPipMode()) {
|
|
304
308
|
this.tasService.disconnectSession();
|
|
305
309
|
}
|
|
306
|
-
interact(
|
|
310
|
+
interact('.publisher-view').unset();
|
|
307
311
|
}
|
|
308
312
|
// Public Methods
|
|
309
313
|
hangUp() {
|
|
@@ -313,7 +317,8 @@ class TasVideocallComponent {
|
|
|
313
317
|
this.tasService.toggleMute();
|
|
314
318
|
}
|
|
315
319
|
minimize() {
|
|
316
|
-
this.tasService.moveMainVideoTo(
|
|
320
|
+
this.tasService.moveMainVideoTo('pip-main-video');
|
|
321
|
+
// Small delay to ensure video is moved before closing modal
|
|
317
322
|
setTimeout(() => this.tasService.enterPipMode(), 50);
|
|
318
323
|
}
|
|
319
324
|
toggleSwap() {
|
|
@@ -326,30 +331,33 @@ class TasVideocallComponent {
|
|
|
326
331
|
}
|
|
327
332
|
// Private Methods
|
|
328
333
|
setupSubscriptions() {
|
|
329
|
-
|
|
334
|
+
// Call state subscription
|
|
335
|
+
this.subscriptions.add(this.tasService.callState$.subscribe(state => {
|
|
330
336
|
this.callState = state;
|
|
331
337
|
if (state === CallState.DISCONNECTED) {
|
|
332
|
-
this.activeModal.close(
|
|
338
|
+
this.activeModal.close('hangup');
|
|
333
339
|
}
|
|
334
340
|
}));
|
|
335
|
-
|
|
341
|
+
// View mode subscription
|
|
342
|
+
this.subscriptions.add(this.tasService.viewMode$.subscribe(mode => {
|
|
336
343
|
if (mode === ViewMode.PIP) {
|
|
337
|
-
this.activeModal.close(
|
|
344
|
+
this.activeModal.close('pip');
|
|
338
345
|
}
|
|
339
346
|
}));
|
|
340
|
-
|
|
347
|
+
// Mute state subscription
|
|
348
|
+
this.subscriptions.add(this.tasService.isMuted$.subscribe(muted => {
|
|
341
349
|
this.isMuted = muted;
|
|
342
350
|
}));
|
|
343
351
|
}
|
|
344
352
|
initializeCall() {
|
|
345
353
|
if (this.isReturningFromPip) {
|
|
354
|
+
// Returning from PiP - just move videos back
|
|
346
355
|
setTimeout(() => this.tasService.moveVideosToFullscreen(), 100);
|
|
347
356
|
}
|
|
348
357
|
else if (this.sessionId && this.token) {
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
.
|
|
352
|
-
console.error("Error connecting to video call:", err);
|
|
358
|
+
// New call - connect to session
|
|
359
|
+
this.tasService.connectSession(this.sessionId, this.token, 'publisher-container', 'subscriber-container').catch(err => {
|
|
360
|
+
console.error('Error connecting to video call:', err);
|
|
353
361
|
});
|
|
354
362
|
}
|
|
355
363
|
}
|
|
@@ -357,69 +365,69 @@ class TasVideocallComponent {
|
|
|
357
365
|
const publisherEl = this.publisherContainer?.nativeElement;
|
|
358
366
|
const subscriberEl = this.subscriberContainer?.nativeElement;
|
|
359
367
|
if (publisherEl) {
|
|
360
|
-
publisherEl.removeAttribute(
|
|
361
|
-
publisherEl.removeAttribute(
|
|
362
|
-
publisherEl.removeAttribute(
|
|
368
|
+
publisherEl.removeAttribute('style');
|
|
369
|
+
publisherEl.removeAttribute('data-x');
|
|
370
|
+
publisherEl.removeAttribute('data-y');
|
|
363
371
|
}
|
|
364
372
|
if (subscriberEl) {
|
|
365
|
-
subscriberEl.removeAttribute(
|
|
366
|
-
subscriberEl.removeAttribute(
|
|
367
|
-
subscriberEl.removeAttribute(
|
|
373
|
+
subscriberEl.removeAttribute('style');
|
|
374
|
+
subscriberEl.removeAttribute('data-x');
|
|
375
|
+
subscriberEl.removeAttribute('data-y');
|
|
368
376
|
}
|
|
369
377
|
}
|
|
370
378
|
initInteract() {
|
|
371
|
-
interact(
|
|
372
|
-
interact(
|
|
379
|
+
interact('.publisher-view').unset();
|
|
380
|
+
interact('.publisher-view')
|
|
373
381
|
.draggable({
|
|
374
382
|
inertia: true,
|
|
375
383
|
modifiers: [
|
|
376
384
|
interact.modifiers.restrictRect({
|
|
377
|
-
restriction:
|
|
378
|
-
endOnly: true
|
|
379
|
-
})
|
|
385
|
+
restriction: 'parent',
|
|
386
|
+
endOnly: true
|
|
387
|
+
})
|
|
380
388
|
],
|
|
381
389
|
autoScroll: true,
|
|
382
390
|
listeners: {
|
|
383
391
|
move: (event) => {
|
|
384
392
|
const target = event.target;
|
|
385
|
-
const x = (parseFloat(target.getAttribute(
|
|
386
|
-
const y = (parseFloat(target.getAttribute(
|
|
393
|
+
const x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx;
|
|
394
|
+
const y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
|
|
387
395
|
target.style.transform = `translate(${x}px, ${y}px)`;
|
|
388
|
-
target.setAttribute(
|
|
389
|
-
target.setAttribute(
|
|
390
|
-
}
|
|
391
|
-
}
|
|
396
|
+
target.setAttribute('data-x', String(x));
|
|
397
|
+
target.setAttribute('data-y', String(y));
|
|
398
|
+
}
|
|
399
|
+
}
|
|
392
400
|
})
|
|
393
401
|
.resizable({
|
|
394
402
|
edges: { left: false, right: true, bottom: true, top: false },
|
|
395
403
|
listeners: {
|
|
396
404
|
move: (event) => {
|
|
397
405
|
const target = event.target;
|
|
398
|
-
let x = parseFloat(target.getAttribute(
|
|
399
|
-
let y = parseFloat(target.getAttribute(
|
|
406
|
+
let x = parseFloat(target.getAttribute('data-x')) || 0;
|
|
407
|
+
let y = parseFloat(target.getAttribute('data-y')) || 0;
|
|
400
408
|
target.style.width = `${event.rect.width}px`;
|
|
401
409
|
target.style.height = `${event.rect.height}px`;
|
|
402
410
|
x += event.deltaRect.left;
|
|
403
411
|
y += event.deltaRect.top;
|
|
404
412
|
target.style.transform = `translate(${x}px, ${y}px)`;
|
|
405
|
-
target.setAttribute(
|
|
406
|
-
target.setAttribute(
|
|
407
|
-
}
|
|
413
|
+
target.setAttribute('data-x', String(x));
|
|
414
|
+
target.setAttribute('data-y', String(y));
|
|
415
|
+
}
|
|
408
416
|
},
|
|
409
417
|
modifiers: [
|
|
410
|
-
interact.modifiers.restrictEdges({ outer:
|
|
418
|
+
interact.modifiers.restrictEdges({ outer: 'parent' }),
|
|
411
419
|
interact.modifiers.restrictSize({ min: { width: 150, height: 100 } }),
|
|
412
|
-
interact.modifiers.aspectRatio({ ratio:
|
|
420
|
+
interact.modifiers.aspectRatio({ ratio: 'preserve' })
|
|
413
421
|
],
|
|
414
|
-
inertia: true
|
|
422
|
+
inertia: true
|
|
415
423
|
});
|
|
416
424
|
}
|
|
417
425
|
}
|
|
418
426
|
TasVideocallComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TasVideocallComponent, deps: [{ token: i1.NgbActiveModal }, { token: TasService }], target: i0.ɵɵFactoryTarget.Component });
|
|
419
|
-
TasVideocallComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TasVideocallComponent, selector: "tas-videocall", inputs: { sessionId: "sessionId", token: "token", isReturningFromPip: "isReturningFromPip" }, viewQueries: [{ propertyName: "publisherContainer", first: true, predicate: ["publisherContainer"], descendants: true }, { propertyName: "subscriberContainer", first: true, predicate: ["subscriberContainer"], descendants: true }], ngImport: i0, template: "<div class=\"tas-videocall-container\">\n
|
|
427
|
+
TasVideocallComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TasVideocallComponent, selector: "tas-videocall", inputs: { sessionId: "sessionId", token: "token", isReturningFromPip: "isReturningFromPip" }, viewQueries: [{ propertyName: "publisherContainer", first: true, predicate: ["publisherContainer"], descendants: true }, { propertyName: "subscriberContainer", first: true, predicate: ["subscriberContainer"], descendants: true }], ngImport: i0, template: "<div class=\"tas-videocall-container\">\n\t<div id=\"subscriber-container\" \n\t\t[class.subscriber-view]=\"isPublisherSmall\" \n\t\t[class.publisher-view]=\"!isPublisherSmall\"\n\t\t#subscriberContainer\n\t\t(dblclick)=\"onDoubleClick()\">\n\t</div>\n\n\t<div id=\"publisher-container\" \n\t\t[class.publisher-view]=\"isPublisherSmall\" \n\t\t[class.subscriber-view]=\"!isPublisherSmall\"\n\t\t#publisherContainer \n\t\t(dblclick)=\"onDoubleClick()\">\n\t</div>\n\t\n\t<div class=\"controls-container\">\n\t\t<button class=\"btn swap-btn\" (click)=\"toggleSwap()\" title=\"Swap view\">\n\t\t\t<i class=\"fa fa-refresh\"></i>\n\t\t</button>\n\t\t<button class=\"btn pip-btn\" (click)=\"minimize()\" title=\"Minimize (Picture in Picture)\">\n\t\t\t<i class=\"fa fa-compress\"></i>\n\t\t</button>\n\t\t<button class=\"btn mute-btn\" [class.muted]=\"isMuted\" (click)=\"toggleMute()\" [title]=\"isMuted ? 'Unmute microphone' : 'Mute microphone'\">\n\t\t\t<i class=\"fa\" [class.fa-microphone]=\"!isMuted\" [class.fa-microphone-slash]=\"isMuted\"></i>\n\t\t</button>\n\t\t<button class=\"btn hangup-btn\" (click)=\"hangUp()\" title=\"Hang up\">\n\t\t\t<i class=\"fa fa-phone\" style=\"transform: rotate(135deg);\"></i>\n\t\t</button>\n\t</div>\n</div>\n\n", styles: [".tas-videocall-container{position:relative;width:100vw;height:100vh;background-color:#000;overflow:hidden}.tas-videocall-container ::ng-deep .OT_edge-bar-item,.tas-videocall-container ::ng-deep .OT_mute,.tas-videocall-container ::ng-deep .OT_audio-level-meter,.tas-videocall-container ::ng-deep .OT_bar,.tas-videocall-container ::ng-deep .OT_name{display:none!important}.tas-videocall-container .subscriber-view{width:100%;height:100%;z-index:1}.tas-videocall-container .publisher-view{position:absolute;top:20px;right:20px;width:200px;height:150px;z-index:2;border:2px solid #fff;border-radius:8px;background-color:#333}.tas-videocall-container .controls-container{display:flex;flex-direction:row;gap:20px;position:absolute;bottom:30px;left:50%;transform:translate(-50%);z-index:3;background-color:#00000080;padding:15px 25px;border-radius:50px;-webkit-backdrop-filter:blur(5px);backdrop-filter:blur(5px)}.tas-videocall-container .controls-container .hangup-btn,.tas-videocall-container .controls-container .swap-btn,.tas-videocall-container .controls-container .pip-btn,.tas-videocall-container .controls-container .mute-btn{width:60px;height:60px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:24px;border:none;box-shadow:0 4px 6px #0000004d;transition:all .2s ease}.tas-videocall-container .controls-container .hangup-btn i,.tas-videocall-container .controls-container .swap-btn i,.tas-videocall-container .controls-container .pip-btn i,.tas-videocall-container .controls-container .mute-btn i{color:#fff}.tas-videocall-container .controls-container .hangup-btn{background:#dc3545}.tas-videocall-container .controls-container .hangup-btn:hover{background:#c82333;transform:scale(1.05)}.tas-videocall-container .controls-container .swap-btn{background:rgba(255,255,255,.2)}.tas-videocall-container .controls-container .swap-btn:hover{background:rgba(255,255,255,.35);transform:scale(1.05)}.tas-videocall-container .controls-container .pip-btn{background:rgba(255,255,255,.2)}.tas-videocall-container .controls-container .pip-btn:hover{background:rgba(255,255,255,.35);transform:scale(1.05)}.tas-videocall-container .controls-container .mute-btn{background:rgba(255,255,255,.2)}.tas-videocall-container .controls-container .mute-btn:hover{background:rgba(255,255,255,.35);transform:scale(1.05)}.tas-videocall-container .controls-container .mute-btn.muted{background:#f39c12}.tas-videocall-container .controls-container .mute-btn.muted:hover{background:#e67e22}\n"] });
|
|
420
428
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TasVideocallComponent, decorators: [{
|
|
421
429
|
type: Component,
|
|
422
|
-
args: [{ selector:
|
|
430
|
+
args: [{ selector: 'tas-videocall', template: "<div class=\"tas-videocall-container\">\n\t<div id=\"subscriber-container\" \n\t\t[class.subscriber-view]=\"isPublisherSmall\" \n\t\t[class.publisher-view]=\"!isPublisherSmall\"\n\t\t#subscriberContainer\n\t\t(dblclick)=\"onDoubleClick()\">\n\t</div>\n\n\t<div id=\"publisher-container\" \n\t\t[class.publisher-view]=\"isPublisherSmall\" \n\t\t[class.subscriber-view]=\"!isPublisherSmall\"\n\t\t#publisherContainer \n\t\t(dblclick)=\"onDoubleClick()\">\n\t</div>\n\t\n\t<div class=\"controls-container\">\n\t\t<button class=\"btn swap-btn\" (click)=\"toggleSwap()\" title=\"Swap view\">\n\t\t\t<i class=\"fa fa-refresh\"></i>\n\t\t</button>\n\t\t<button class=\"btn pip-btn\" (click)=\"minimize()\" title=\"Minimize (Picture in Picture)\">\n\t\t\t<i class=\"fa fa-compress\"></i>\n\t\t</button>\n\t\t<button class=\"btn mute-btn\" [class.muted]=\"isMuted\" (click)=\"toggleMute()\" [title]=\"isMuted ? 'Unmute microphone' : 'Mute microphone'\">\n\t\t\t<i class=\"fa\" [class.fa-microphone]=\"!isMuted\" [class.fa-microphone-slash]=\"isMuted\"></i>\n\t\t</button>\n\t\t<button class=\"btn hangup-btn\" (click)=\"hangUp()\" title=\"Hang up\">\n\t\t\t<i class=\"fa fa-phone\" style=\"transform: rotate(135deg);\"></i>\n\t\t</button>\n\t</div>\n</div>\n\n", styles: [".tas-videocall-container{position:relative;width:100vw;height:100vh;background-color:#000;overflow:hidden}.tas-videocall-container ::ng-deep .OT_edge-bar-item,.tas-videocall-container ::ng-deep .OT_mute,.tas-videocall-container ::ng-deep .OT_audio-level-meter,.tas-videocall-container ::ng-deep .OT_bar,.tas-videocall-container ::ng-deep .OT_name{display:none!important}.tas-videocall-container .subscriber-view{width:100%;height:100%;z-index:1}.tas-videocall-container .publisher-view{position:absolute;top:20px;right:20px;width:200px;height:150px;z-index:2;border:2px solid #fff;border-radius:8px;background-color:#333}.tas-videocall-container .controls-container{display:flex;flex-direction:row;gap:20px;position:absolute;bottom:30px;left:50%;transform:translate(-50%);z-index:3;background-color:#00000080;padding:15px 25px;border-radius:50px;-webkit-backdrop-filter:blur(5px);backdrop-filter:blur(5px)}.tas-videocall-container .controls-container .hangup-btn,.tas-videocall-container .controls-container .swap-btn,.tas-videocall-container .controls-container .pip-btn,.tas-videocall-container .controls-container .mute-btn{width:60px;height:60px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:24px;border:none;box-shadow:0 4px 6px #0000004d;transition:all .2s ease}.tas-videocall-container .controls-container .hangup-btn i,.tas-videocall-container .controls-container .swap-btn i,.tas-videocall-container .controls-container .pip-btn i,.tas-videocall-container .controls-container .mute-btn i{color:#fff}.tas-videocall-container .controls-container .hangup-btn{background:#dc3545}.tas-videocall-container .controls-container .hangup-btn:hover{background:#c82333;transform:scale(1.05)}.tas-videocall-container .controls-container .swap-btn{background:rgba(255,255,255,.2)}.tas-videocall-container .controls-container .swap-btn:hover{background:rgba(255,255,255,.35);transform:scale(1.05)}.tas-videocall-container .controls-container .pip-btn{background:rgba(255,255,255,.2)}.tas-videocall-container .controls-container .pip-btn:hover{background:rgba(255,255,255,.35);transform:scale(1.05)}.tas-videocall-container .controls-container .mute-btn{background:rgba(255,255,255,.2)}.tas-videocall-container .controls-container .mute-btn:hover{background:rgba(255,255,255,.35);transform:scale(1.05)}.tas-videocall-container .controls-container .mute-btn.muted{background:#f39c12}.tas-videocall-container .controls-container .mute-btn.muted:hover{background:#e67e22}\n"] }]
|
|
423
431
|
}], ctorParameters: function () { return [{ type: i1.NgbActiveModal }, { type: TasService }]; }, propDecorators: { sessionId: [{
|
|
424
432
|
type: Input
|
|
425
433
|
}], token: [{
|
|
@@ -428,124 +436,279 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
428
436
|
type: Input
|
|
429
437
|
}], publisherContainer: [{
|
|
430
438
|
type: ViewChild,
|
|
431
|
-
args: [
|
|
439
|
+
args: ['publisherContainer']
|
|
432
440
|
}], subscriberContainer: [{
|
|
433
441
|
type: ViewChild,
|
|
434
|
-
args: [
|
|
442
|
+
args: ['subscriberContainer']
|
|
435
443
|
}] } });
|
|
436
444
|
|
|
437
|
-
|
|
438
|
-
|
|
445
|
+
var WaitingRoomState;
|
|
446
|
+
(function (WaitingRoomState) {
|
|
447
|
+
WaitingRoomState["IDLE"] = "IDLE";
|
|
448
|
+
WaitingRoomState["CREATING_ROOM"] = "CREATING_ROOM";
|
|
449
|
+
WaitingRoomState["GETTING_TOKEN"] = "GETTING_TOKEN";
|
|
450
|
+
WaitingRoomState["READY"] = "READY";
|
|
451
|
+
WaitingRoomState["ERROR"] = "ERROR";
|
|
452
|
+
})(WaitingRoomState || (WaitingRoomState = {}));
|
|
453
|
+
class TasWaitingRoomComponent {
|
|
454
|
+
constructor(activeModal, tasService, modalService) {
|
|
455
|
+
this.activeModal = activeModal;
|
|
439
456
|
this.tasService = tasService;
|
|
440
457
|
this.modalService = modalService;
|
|
441
|
-
|
|
442
|
-
this.
|
|
443
|
-
this.
|
|
444
|
-
this.tenantId =
|
|
458
|
+
// Room configuration inputs
|
|
459
|
+
this.appointmentId = 1;
|
|
460
|
+
this.product = 'uell';
|
|
461
|
+
this.tenantId = '';
|
|
462
|
+
this.regularUserIds = [];
|
|
463
|
+
this.moderatorUserIds = [];
|
|
464
|
+
// Component state
|
|
465
|
+
this.state = WaitingRoomState.IDLE;
|
|
466
|
+
this.WaitingRoomState = WaitingRoomState; // Expose enum to template
|
|
467
|
+
this.errorMessage = '';
|
|
468
|
+
// Session data
|
|
469
|
+
this.sessionId = '';
|
|
470
|
+
this.token = '';
|
|
471
|
+
this.users = [];
|
|
445
472
|
this.subscriptions = new Subscription();
|
|
446
|
-
this.
|
|
473
|
+
this.videoCallModalRef = null;
|
|
447
474
|
}
|
|
448
475
|
ngOnInit() {
|
|
449
|
-
this.
|
|
476
|
+
this.buildUsersArray();
|
|
450
477
|
this.setupViewModeSubscription();
|
|
451
478
|
}
|
|
452
479
|
ngOnDestroy() {
|
|
453
480
|
this.subscriptions.unsubscribe();
|
|
454
481
|
}
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
482
|
+
/**
|
|
483
|
+
* Creates the room and fetches the token
|
|
484
|
+
*/
|
|
485
|
+
createRoom() {
|
|
486
|
+
if (!this.tenantId || !this.currentUser?.name) {
|
|
487
|
+
this.state = WaitingRoomState.ERROR;
|
|
488
|
+
this.errorMessage = 'Missing configuration data (tenant or user)';
|
|
458
489
|
return;
|
|
459
490
|
}
|
|
460
|
-
this.
|
|
461
|
-
this.
|
|
462
|
-
|
|
491
|
+
this.state = WaitingRoomState.CREATING_ROOM;
|
|
492
|
+
this.errorMessage = '';
|
|
493
|
+
const body = {
|
|
494
|
+
roomType: TasRoomType.TAS,
|
|
495
|
+
type: TasSessionType.SPONTANEOUS,
|
|
463
496
|
tenant: this.tenantId,
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
.
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
.
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
sessionId,
|
|
482
|
-
token: tokenResponse.content.token,
|
|
483
|
-
},
|
|
484
|
-
];
|
|
485
|
-
}));
|
|
486
|
-
}))
|
|
487
|
-
.subscribe({
|
|
488
|
-
next: ({ sessionId, token }) => {
|
|
489
|
-
this.isLoading = false;
|
|
490
|
-
this.openVideoCallModal(sessionId, token);
|
|
497
|
+
appointmentId: this.appointmentId,
|
|
498
|
+
users: this.users,
|
|
499
|
+
product: this.product
|
|
500
|
+
};
|
|
501
|
+
this.subscriptions.add(this.tasService.createRoom(body).pipe(switchMap(response => {
|
|
502
|
+
this.sessionId = response.content.sessionId;
|
|
503
|
+
this.state = WaitingRoomState.GETTING_TOKEN;
|
|
504
|
+
return this.tasService.generateToken({
|
|
505
|
+
sessionId: this.sessionId,
|
|
506
|
+
name: this.currentUser.name,
|
|
507
|
+
lastname: this.currentUser.lastname,
|
|
508
|
+
roleVC: this.currentUser.role
|
|
509
|
+
});
|
|
510
|
+
})).subscribe({
|
|
511
|
+
next: (tokenResponse) => {
|
|
512
|
+
this.token = tokenResponse.content.token;
|
|
513
|
+
this.state = WaitingRoomState.READY;
|
|
491
514
|
},
|
|
492
515
|
error: (err) => {
|
|
493
|
-
console.error(
|
|
494
|
-
this.
|
|
495
|
-
|
|
516
|
+
console.error('Error creating room or getting token:', err);
|
|
517
|
+
this.state = WaitingRoomState.ERROR;
|
|
518
|
+
this.errorMessage = 'Error creating room. Please try again.';
|
|
519
|
+
}
|
|
496
520
|
}));
|
|
497
521
|
}
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
522
|
+
/**
|
|
523
|
+
* Joins the video call session
|
|
524
|
+
*/
|
|
525
|
+
joinSession() {
|
|
526
|
+
if (!this.sessionId || !this.token) {
|
|
527
|
+
this.errorMessage = 'Cannot join session. Incomplete data.';
|
|
502
528
|
return;
|
|
503
529
|
}
|
|
504
|
-
|
|
505
|
-
this.
|
|
530
|
+
// Close waiting room and open video call
|
|
531
|
+
this.activeModal.close('joining');
|
|
532
|
+
this.openVideoCallModal();
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* Closes the waiting room
|
|
536
|
+
*/
|
|
537
|
+
cancel() {
|
|
538
|
+
this.activeModal.dismiss('cancel');
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* Retry after an error
|
|
542
|
+
*/
|
|
543
|
+
retry() {
|
|
544
|
+
this.state = WaitingRoomState.IDLE;
|
|
545
|
+
this.errorMessage = '';
|
|
546
|
+
this.sessionId = '';
|
|
547
|
+
this.token = '';
|
|
548
|
+
}
|
|
549
|
+
// Private Methods
|
|
550
|
+
buildUsersArray() {
|
|
551
|
+
this.users = [];
|
|
552
|
+
// Add owners from input
|
|
553
|
+
this.ownerUserIds.forEach(id => {
|
|
554
|
+
this.users.push({ userExternalId: id, rol: TasUserRole.OWNER });
|
|
555
|
+
});
|
|
556
|
+
// Add regular users from input
|
|
557
|
+
this.regularUserIds.forEach(id => {
|
|
558
|
+
this.users.push({ userExternalId: id, rol: TasUserRole.USER });
|
|
559
|
+
});
|
|
560
|
+
// Add moderators from input
|
|
561
|
+
this.moderatorUserIds.forEach(id => {
|
|
562
|
+
this.users.push({ userExternalId: id, rol: TasUserRole.MODERATOR });
|
|
563
|
+
});
|
|
506
564
|
}
|
|
507
565
|
setupViewModeSubscription() {
|
|
508
|
-
this.subscriptions.add(this.tasService.viewMode$.subscribe(
|
|
566
|
+
this.subscriptions.add(this.tasService.viewMode$.subscribe(mode => {
|
|
567
|
+
// Re-open video call modal when returning from PiP mode
|
|
509
568
|
if (mode === ViewMode.FULLSCREEN &&
|
|
510
569
|
this.tasService.isCallActive() &&
|
|
511
|
-
!this.
|
|
570
|
+
!this.videoCallModalRef) {
|
|
512
571
|
const sessionId = this.tasService.sessionId;
|
|
513
572
|
const token = this.tasService.token;
|
|
514
573
|
if (sessionId && token) {
|
|
515
|
-
this.openVideoCallModal(
|
|
574
|
+
this.openVideoCallModal(true);
|
|
516
575
|
}
|
|
517
576
|
}
|
|
518
577
|
}));
|
|
519
578
|
}
|
|
520
|
-
openVideoCallModal(
|
|
521
|
-
this.
|
|
522
|
-
size:
|
|
523
|
-
windowClass:
|
|
579
|
+
openVideoCallModal(isReturningFromPip = false) {
|
|
580
|
+
this.videoCallModalRef = this.modalService.open(TasVideocallComponent, {
|
|
581
|
+
size: 'xl',
|
|
582
|
+
windowClass: 'tas-video-modal',
|
|
583
|
+
backdrop: 'static',
|
|
584
|
+
keyboard: false
|
|
585
|
+
});
|
|
586
|
+
const sessionIdToUse = this.sessionId || this.tasService.sessionId;
|
|
587
|
+
const tokenToUse = this.token || this.tasService.token;
|
|
588
|
+
this.videoCallModalRef.componentInstance.sessionId = sessionIdToUse;
|
|
589
|
+
this.videoCallModalRef.componentInstance.token = tokenToUse;
|
|
590
|
+
this.videoCallModalRef.componentInstance.isReturningFromPip = isReturningFromPip;
|
|
591
|
+
this.videoCallModalRef.result.then(() => { this.videoCallModalRef = null; }, () => { this.videoCallModalRef = null; });
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
TasWaitingRoomComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TasWaitingRoomComponent, deps: [{ token: i1.NgbActiveModal }, { token: TasService }, { token: i1.NgbModal }], target: i0.ɵɵFactoryTarget.Component });
|
|
595
|
+
TasWaitingRoomComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TasWaitingRoomComponent, selector: "tas-waiting-room", inputs: { appointmentId: "appointmentId", product: "product", tenantId: "tenantId", currentUser: "currentUser", ownerUserIds: "ownerUserIds", regularUserIds: "regularUserIds", moderatorUserIds: "moderatorUserIds" }, ngImport: i0, template: "<div class=\"tas-waiting-room\">\n\t<!-- Header -->\n\t<div class=\"waiting-room-header\">\n\t\t<div class=\"header-icon\">\n\t\t\t<i class=\"fa fa-video-camera\"></i>\n\t\t</div>\n\t\t<h2 class=\"header-title\">Waiting Room</h2>\n\t\t<p class=\"header-subtitle\">Prepare for your video call</p>\n\t\t<button type=\"button\" class=\"close-btn\" (click)=\"cancel()\" aria-label=\"Close\">\n\t\t\t<span aria-hidden=\"true\">×</span>\n\t\t</button>\n\t</div>\n\n\t<!-- Content -->\n\t<div class=\"waiting-room-content\">\n\t\t<!-- IDLE State -->\n\t\t<div class=\"state-container\" *ngIf=\"state === WaitingRoomState.IDLE\">\n\t\t\t<div class=\"state-icon idle\">\n\t\t\t\t<i class=\"fa fa-plus-circle\"></i>\n\t\t\t</div>\n\t\t\t<p class=\"state-message\">\n\t\t\t\tCreate a new video call room\n\t\t\t</p>\n\t\t\t<p class=\"state-submessage\">\n\t\t\t\tPress the button to begin\n\t\t\t</p>\n\t\t\t<button \n\t\t\t\ttype=\"button\" \n\t\t\t\tclass=\"btn action-btn create-btn\"\n\t\t\t\t(click)=\"createRoom()\">\n\t\t\t\t<i class=\"fa fa-plus\"></i>\n\t\t\t\tCreate Room\n\t\t\t</button>\n\t\t</div>\n\n\t\t<!-- CREATING_ROOM State -->\n\t\t<div class=\"state-container\" *ngIf=\"state === WaitingRoomState.CREATING_ROOM\">\n\t\t\t<div class=\"state-icon loading\">\n\t\t\t\t<div class=\"spinner\"></div>\n\t\t\t</div>\n\t\t\t<p class=\"state-message\">\n\t\t\t\tCreating video call room...\n\t\t\t</p>\n\t\t\t<div class=\"progress-steps\">\n\t\t\t\t<div class=\"step active\">\n\t\t\t\t\t<span class=\"step-indicator\"></span>\n\t\t\t\t\t<span class=\"step-label\">Creating</span>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"step\">\n\t\t\t\t\t<span class=\"step-indicator\"></span>\n\t\t\t\t\t<span class=\"step-label\">Access</span>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"step\">\n\t\t\t\t\t<span class=\"step-indicator\"></span>\n\t\t\t\t\t<span class=\"step-label\">Ready</span>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<!-- GETTING_TOKEN State -->\n\t\t<div class=\"state-container\" *ngIf=\"state === WaitingRoomState.GETTING_TOKEN\">\n\t\t\t<div class=\"state-icon loading\">\n\t\t\t\t<div class=\"spinner\"></div>\n\t\t\t</div>\n\t\t\t<p class=\"state-message\">\n\t\t\t\tPreparing room access...\n\t\t\t</p>\n\t\t\t<div class=\"progress-steps\">\n\t\t\t\t<div class=\"step completed\">\n\t\t\t\t\t<span class=\"step-indicator\"><i class=\"fa fa-check\"></i></span>\n\t\t\t\t\t<span class=\"step-label\">Created</span>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"step active\">\n\t\t\t\t\t<span class=\"step-indicator\"></span>\n\t\t\t\t\t<span class=\"step-label\">Access</span>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"step\">\n\t\t\t\t\t<span class=\"step-indicator\"></span>\n\t\t\t\t\t<span class=\"step-label\">Ready</span>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<!-- READY State -->\n\t\t<div class=\"state-container\" *ngIf=\"state === WaitingRoomState.READY\">\n\t\t\t<div class=\"state-icon ready\">\n\t\t\t\t<i class=\"fa fa-check-circle\"></i>\n\t\t\t</div>\n\t\t\t<p class=\"state-message success\">\n\t\t\t\tRoom is ready!\n\t\t\t</p>\n\t\t\t<p class=\"state-submessage\">\n\t\t\t\tYou can join the video call when ready\n\t\t\t</p>\n\t\t\t<div class=\"progress-steps\">\n\t\t\t\t<div class=\"step completed\">\n\t\t\t\t\t<span class=\"step-indicator\"><i class=\"fa fa-check\"></i></span>\n\t\t\t\t\t<span class=\"step-label\">Created</span>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"step completed\">\n\t\t\t\t\t<span class=\"step-indicator\"><i class=\"fa fa-check\"></i></span>\n\t\t\t\t\t<span class=\"step-label\">Access</span>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"step completed\">\n\t\t\t\t\t<span class=\"step-indicator\"><i class=\"fa fa-check\"></i></span>\n\t\t\t\t\t<span class=\"step-label\">Ready</span>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<button \n\t\t\t\ttype=\"button\" \n\t\t\t\tclass=\"btn action-btn join-btn\"\n\t\t\t\t(click)=\"joinSession()\">\n\t\t\t\t<i class=\"fa fa-sign-in\"></i>\n\t\t\t\tJoin Session\n\t\t\t</button>\n\t\t</div>\n\n\t\t<!-- ERROR State -->\n\t\t<div class=\"state-container\" *ngIf=\"state === WaitingRoomState.ERROR\">\n\t\t\t<div class=\"state-icon error\">\n\t\t\t\t<i class=\"fa fa-exclamation-triangle\"></i>\n\t\t\t</div>\n\t\t\t<p class=\"state-message error\">\n\t\t\t\tAn error occurred\n\t\t\t</p>\n\t\t\t<p class=\"error-details\" *ngIf=\"errorMessage\">\n\t\t\t\t{{ errorMessage }}\n\t\t\t</p>\n\t\t\t<button \n\t\t\t\ttype=\"button\" \n\t\t\t\tclass=\"btn action-btn retry-btn\"\n\t\t\t\t(click)=\"retry()\">\n\t\t\t\t<i class=\"fa fa-refresh\"></i>\n\t\t\t\tRetry\n\t\t\t</button>\n\t\t</div>\n\t</div>\n\n\t<!-- Footer -->\n\t<div class=\"waiting-room-footer\">\n\t\t<button \n\t\t\ttype=\"button\" \n\t\t\tclass=\"btn cancel-btn\"\n\t\t\t(click)=\"cancel()\">\n\t\t\tCancel\n\t\t</button>\n\t</div>\n</div>\n\n", styles: [".tas-waiting-room{display:flex;flex-direction:column;min-height:420px;background:#ffffff;border-radius:5px;overflow:hidden}.waiting-room-header{position:relative;padding:32px 40px 24px;text-align:center;border-bottom:1px solid #e9ecef}.waiting-room-header .header-icon{width:72px;height:72px;margin:0 auto 16px;background:linear-gradient(135deg,#1da4b1 0%,#0077b3 100%);border-radius:50%;display:flex;align-items:center;justify-content:center;box-shadow:0 4px 16px #1da4b140}.waiting-room-header .header-icon i{font-size:28px;color:#fff}.waiting-room-header .header-title{margin:0 0 8px;font-size:20px;font-weight:700;line-height:28px;color:#212529}.waiting-room-header .header-subtitle{margin:0;font-size:14px;color:#6c757d;font-weight:400}.waiting-room-header .close-btn{position:absolute;top:16px;right:16px;width:32px;height:32px;border:none;background:transparent;border-radius:4px;color:#6c757d;cursor:pointer;transition:all .2s ease;font-size:20px}.waiting-room-header .close-btn:hover{background:#f8f9fa;color:#212529}.waiting-room-content{flex:1;display:flex;align-items:center;justify-content:center;padding:32px 40px;background:#ffffff}.state-container{text-align:center;max-width:360px;width:100%}.state-icon{width:80px;height:80px;margin:0 auto 24px;border-radius:50%;display:flex;align-items:center;justify-content:center}.state-icon i{font-size:36px}.state-icon.idle{background:rgba(29,164,177,.1);border:2px dashed #1da4b1}.state-icon.idle i{color:#1da4b1}.state-icon.loading{background:rgba(29,164,177,.1);border:2px solid #1da4b1}.state-icon.ready{background:linear-gradient(135deg,#1da4b1 0%,#38b89a 100%);box-shadow:0 4px 16px #1da4b14d}.state-icon.ready i{color:#fff}.state-icon.error{background:rgba(238,49,107,.1);border:2px solid #ee316b}.state-icon.error i{color:#ee316b}.spinner{width:40px;height:40px;border:3px solid #e9ecef;border-top-color:#1da4b1;border-radius:50%;animation:spin 1s linear infinite}.state-message{font-size:16px;font-weight:600;margin:0 0 8px;color:#212529;line-height:24px}.state-message.success{color:#1da4b1}.state-message.error{color:#ee316b}.state-submessage{font-size:14px;color:#6c757d;margin:0 0 24px;font-weight:400}.error-details{font-size:13px;color:#ee316b;margin:0 0 24px;padding:12px 16px;background:rgba(238,49,107,.08);border-radius:8px;border:1px solid rgba(238,49,107,.2)}.progress-steps{display:flex;justify-content:center;gap:24px;margin:24px 0 32px}.step{display:flex;flex-direction:column;align-items:center;gap:8px}.step .step-indicator{width:32px;height:32px;border-radius:50%;background:#f8f9fa;border:2px solid #e9ecef;display:flex;align-items:center;justify-content:center;transition:all .3s ease}.step .step-indicator i{font-size:12px;color:#fff}.step .step-label{font-size:11px;color:#6c757d;text-transform:uppercase;letter-spacing:.5px;font-weight:500}.step.active .step-indicator{background:rgba(29,164,177,.1);border-color:#1da4b1;animation:pulse-active 1.5s infinite}.step.active .step-label{color:#1da4b1;font-weight:600}.step.completed .step-indicator{background:#1da4b1;border-color:#1da4b1}.step.completed .step-label{color:#1da4b1;font-weight:600}.action-btn{padding:12px 32px;font-size:16px;font-weight:600;border-radius:4px;border:none;cursor:pointer;transition:all .2s ease;display:inline-flex;align-items:center;gap:10px}.action-btn i{font-size:16px}.action-btn.create-btn{background:#0077b3;color:#fff;box-shadow:0 2px 8px #0077b340}.action-btn.create-btn:hover{background:#005c8a;box-shadow:0 4px 12px #0077b359}.action-btn.create-btn:active{transform:translateY(1px)}.action-btn.join-btn{background:#1da4b1;color:#fff;box-shadow:0 2px 8px #1da4b140;animation:pulse-ready 2s infinite}.action-btn.join-btn:hover{background:#17848e;box-shadow:0 4px 12px #1da4b159}.action-btn.join-btn:active{transform:translateY(1px)}.action-btn.retry-btn{background:transparent;color:#6c757d;border:1px solid #e9ecef}.action-btn.retry-btn:hover{background:#f8f9fa;border-color:#6c757d;color:#212529}.waiting-room-footer{padding:16px 40px 24px;background:#ffffff;border-top:1px solid #e9ecef;display:flex;justify-content:center}.waiting-room-footer .cancel-btn{padding:10px 24px;font-size:14px;font-weight:600;border-radius:4px;background:transparent;color:#6c757d;border:none;cursor:pointer;transition:all .2s ease}.waiting-room-footer .cancel-btn:hover{background:#f8f9fa;color:#212529}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse-active{0%,to{box-shadow:0 0 #1da4b166}50%{box-shadow:0 0 0 8px #1da4b100}}@keyframes pulse-ready{0%,to{box-shadow:0 2px 8px #1da4b140}50%{box-shadow:0 4px 16px #1da4b166}}@media (max-width: 576px){.tas-waiting-room{min-height:380px}.waiting-room-header{padding:24px 24px 20px}.waiting-room-header .header-icon{width:56px;height:56px}.waiting-room-header .header-icon i{font-size:22px}.waiting-room-header .header-title{font-size:18px}.waiting-room-content{padding:24px}.state-icon{width:64px;height:64px}.state-icon i{font-size:28px}.spinner{width:32px;height:32px}.progress-steps{gap:12px}.step .step-indicator{width:28px;height:28px}.step .step-label{font-size:9px}.action-btn{padding:10px 24px;font-size:14px}.waiting-room-footer{padding:16px 24px 20px}}\n"], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
596
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TasWaitingRoomComponent, decorators: [{
|
|
597
|
+
type: Component,
|
|
598
|
+
args: [{ selector: 'tas-waiting-room', template: "<div class=\"tas-waiting-room\">\n\t<!-- Header -->\n\t<div class=\"waiting-room-header\">\n\t\t<div class=\"header-icon\">\n\t\t\t<i class=\"fa fa-video-camera\"></i>\n\t\t</div>\n\t\t<h2 class=\"header-title\">Waiting Room</h2>\n\t\t<p class=\"header-subtitle\">Prepare for your video call</p>\n\t\t<button type=\"button\" class=\"close-btn\" (click)=\"cancel()\" aria-label=\"Close\">\n\t\t\t<span aria-hidden=\"true\">×</span>\n\t\t</button>\n\t</div>\n\n\t<!-- Content -->\n\t<div class=\"waiting-room-content\">\n\t\t<!-- IDLE State -->\n\t\t<div class=\"state-container\" *ngIf=\"state === WaitingRoomState.IDLE\">\n\t\t\t<div class=\"state-icon idle\">\n\t\t\t\t<i class=\"fa fa-plus-circle\"></i>\n\t\t\t</div>\n\t\t\t<p class=\"state-message\">\n\t\t\t\tCreate a new video call room\n\t\t\t</p>\n\t\t\t<p class=\"state-submessage\">\n\t\t\t\tPress the button to begin\n\t\t\t</p>\n\t\t\t<button \n\t\t\t\ttype=\"button\" \n\t\t\t\tclass=\"btn action-btn create-btn\"\n\t\t\t\t(click)=\"createRoom()\">\n\t\t\t\t<i class=\"fa fa-plus\"></i>\n\t\t\t\tCreate Room\n\t\t\t</button>\n\t\t</div>\n\n\t\t<!-- CREATING_ROOM State -->\n\t\t<div class=\"state-container\" *ngIf=\"state === WaitingRoomState.CREATING_ROOM\">\n\t\t\t<div class=\"state-icon loading\">\n\t\t\t\t<div class=\"spinner\"></div>\n\t\t\t</div>\n\t\t\t<p class=\"state-message\">\n\t\t\t\tCreating video call room...\n\t\t\t</p>\n\t\t\t<div class=\"progress-steps\">\n\t\t\t\t<div class=\"step active\">\n\t\t\t\t\t<span class=\"step-indicator\"></span>\n\t\t\t\t\t<span class=\"step-label\">Creating</span>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"step\">\n\t\t\t\t\t<span class=\"step-indicator\"></span>\n\t\t\t\t\t<span class=\"step-label\">Access</span>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"step\">\n\t\t\t\t\t<span class=\"step-indicator\"></span>\n\t\t\t\t\t<span class=\"step-label\">Ready</span>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<!-- GETTING_TOKEN State -->\n\t\t<div class=\"state-container\" *ngIf=\"state === WaitingRoomState.GETTING_TOKEN\">\n\t\t\t<div class=\"state-icon loading\">\n\t\t\t\t<div class=\"spinner\"></div>\n\t\t\t</div>\n\t\t\t<p class=\"state-message\">\n\t\t\t\tPreparing room access...\n\t\t\t</p>\n\t\t\t<div class=\"progress-steps\">\n\t\t\t\t<div class=\"step completed\">\n\t\t\t\t\t<span class=\"step-indicator\"><i class=\"fa fa-check\"></i></span>\n\t\t\t\t\t<span class=\"step-label\">Created</span>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"step active\">\n\t\t\t\t\t<span class=\"step-indicator\"></span>\n\t\t\t\t\t<span class=\"step-label\">Access</span>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"step\">\n\t\t\t\t\t<span class=\"step-indicator\"></span>\n\t\t\t\t\t<span class=\"step-label\">Ready</span>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<!-- READY State -->\n\t\t<div class=\"state-container\" *ngIf=\"state === WaitingRoomState.READY\">\n\t\t\t<div class=\"state-icon ready\">\n\t\t\t\t<i class=\"fa fa-check-circle\"></i>\n\t\t\t</div>\n\t\t\t<p class=\"state-message success\">\n\t\t\t\tRoom is ready!\n\t\t\t</p>\n\t\t\t<p class=\"state-submessage\">\n\t\t\t\tYou can join the video call when ready\n\t\t\t</p>\n\t\t\t<div class=\"progress-steps\">\n\t\t\t\t<div class=\"step completed\">\n\t\t\t\t\t<span class=\"step-indicator\"><i class=\"fa fa-check\"></i></span>\n\t\t\t\t\t<span class=\"step-label\">Created</span>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"step completed\">\n\t\t\t\t\t<span class=\"step-indicator\"><i class=\"fa fa-check\"></i></span>\n\t\t\t\t\t<span class=\"step-label\">Access</span>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"step completed\">\n\t\t\t\t\t<span class=\"step-indicator\"><i class=\"fa fa-check\"></i></span>\n\t\t\t\t\t<span class=\"step-label\">Ready</span>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<button \n\t\t\t\ttype=\"button\" \n\t\t\t\tclass=\"btn action-btn join-btn\"\n\t\t\t\t(click)=\"joinSession()\">\n\t\t\t\t<i class=\"fa fa-sign-in\"></i>\n\t\t\t\tJoin Session\n\t\t\t</button>\n\t\t</div>\n\n\t\t<!-- ERROR State -->\n\t\t<div class=\"state-container\" *ngIf=\"state === WaitingRoomState.ERROR\">\n\t\t\t<div class=\"state-icon error\">\n\t\t\t\t<i class=\"fa fa-exclamation-triangle\"></i>\n\t\t\t</div>\n\t\t\t<p class=\"state-message error\">\n\t\t\t\tAn error occurred\n\t\t\t</p>\n\t\t\t<p class=\"error-details\" *ngIf=\"errorMessage\">\n\t\t\t\t{{ errorMessage }}\n\t\t\t</p>\n\t\t\t<button \n\t\t\t\ttype=\"button\" \n\t\t\t\tclass=\"btn action-btn retry-btn\"\n\t\t\t\t(click)=\"retry()\">\n\t\t\t\t<i class=\"fa fa-refresh\"></i>\n\t\t\t\tRetry\n\t\t\t</button>\n\t\t</div>\n\t</div>\n\n\t<!-- Footer -->\n\t<div class=\"waiting-room-footer\">\n\t\t<button \n\t\t\ttype=\"button\" \n\t\t\tclass=\"btn cancel-btn\"\n\t\t\t(click)=\"cancel()\">\n\t\t\tCancel\n\t\t</button>\n\t</div>\n</div>\n\n", styles: [".tas-waiting-room{display:flex;flex-direction:column;min-height:420px;background:#ffffff;border-radius:5px;overflow:hidden}.waiting-room-header{position:relative;padding:32px 40px 24px;text-align:center;border-bottom:1px solid #e9ecef}.waiting-room-header .header-icon{width:72px;height:72px;margin:0 auto 16px;background:linear-gradient(135deg,#1da4b1 0%,#0077b3 100%);border-radius:50%;display:flex;align-items:center;justify-content:center;box-shadow:0 4px 16px #1da4b140}.waiting-room-header .header-icon i{font-size:28px;color:#fff}.waiting-room-header .header-title{margin:0 0 8px;font-size:20px;font-weight:700;line-height:28px;color:#212529}.waiting-room-header .header-subtitle{margin:0;font-size:14px;color:#6c757d;font-weight:400}.waiting-room-header .close-btn{position:absolute;top:16px;right:16px;width:32px;height:32px;border:none;background:transparent;border-radius:4px;color:#6c757d;cursor:pointer;transition:all .2s ease;font-size:20px}.waiting-room-header .close-btn:hover{background:#f8f9fa;color:#212529}.waiting-room-content{flex:1;display:flex;align-items:center;justify-content:center;padding:32px 40px;background:#ffffff}.state-container{text-align:center;max-width:360px;width:100%}.state-icon{width:80px;height:80px;margin:0 auto 24px;border-radius:50%;display:flex;align-items:center;justify-content:center}.state-icon i{font-size:36px}.state-icon.idle{background:rgba(29,164,177,.1);border:2px dashed #1da4b1}.state-icon.idle i{color:#1da4b1}.state-icon.loading{background:rgba(29,164,177,.1);border:2px solid #1da4b1}.state-icon.ready{background:linear-gradient(135deg,#1da4b1 0%,#38b89a 100%);box-shadow:0 4px 16px #1da4b14d}.state-icon.ready i{color:#fff}.state-icon.error{background:rgba(238,49,107,.1);border:2px solid #ee316b}.state-icon.error i{color:#ee316b}.spinner{width:40px;height:40px;border:3px solid #e9ecef;border-top-color:#1da4b1;border-radius:50%;animation:spin 1s linear infinite}.state-message{font-size:16px;font-weight:600;margin:0 0 8px;color:#212529;line-height:24px}.state-message.success{color:#1da4b1}.state-message.error{color:#ee316b}.state-submessage{font-size:14px;color:#6c757d;margin:0 0 24px;font-weight:400}.error-details{font-size:13px;color:#ee316b;margin:0 0 24px;padding:12px 16px;background:rgba(238,49,107,.08);border-radius:8px;border:1px solid rgba(238,49,107,.2)}.progress-steps{display:flex;justify-content:center;gap:24px;margin:24px 0 32px}.step{display:flex;flex-direction:column;align-items:center;gap:8px}.step .step-indicator{width:32px;height:32px;border-radius:50%;background:#f8f9fa;border:2px solid #e9ecef;display:flex;align-items:center;justify-content:center;transition:all .3s ease}.step .step-indicator i{font-size:12px;color:#fff}.step .step-label{font-size:11px;color:#6c757d;text-transform:uppercase;letter-spacing:.5px;font-weight:500}.step.active .step-indicator{background:rgba(29,164,177,.1);border-color:#1da4b1;animation:pulse-active 1.5s infinite}.step.active .step-label{color:#1da4b1;font-weight:600}.step.completed .step-indicator{background:#1da4b1;border-color:#1da4b1}.step.completed .step-label{color:#1da4b1;font-weight:600}.action-btn{padding:12px 32px;font-size:16px;font-weight:600;border-radius:4px;border:none;cursor:pointer;transition:all .2s ease;display:inline-flex;align-items:center;gap:10px}.action-btn i{font-size:16px}.action-btn.create-btn{background:#0077b3;color:#fff;box-shadow:0 2px 8px #0077b340}.action-btn.create-btn:hover{background:#005c8a;box-shadow:0 4px 12px #0077b359}.action-btn.create-btn:active{transform:translateY(1px)}.action-btn.join-btn{background:#1da4b1;color:#fff;box-shadow:0 2px 8px #1da4b140;animation:pulse-ready 2s infinite}.action-btn.join-btn:hover{background:#17848e;box-shadow:0 4px 12px #1da4b159}.action-btn.join-btn:active{transform:translateY(1px)}.action-btn.retry-btn{background:transparent;color:#6c757d;border:1px solid #e9ecef}.action-btn.retry-btn:hover{background:#f8f9fa;border-color:#6c757d;color:#212529}.waiting-room-footer{padding:16px 40px 24px;background:#ffffff;border-top:1px solid #e9ecef;display:flex;justify-content:center}.waiting-room-footer .cancel-btn{padding:10px 24px;font-size:14px;font-weight:600;border-radius:4px;background:transparent;color:#6c757d;border:none;cursor:pointer;transition:all .2s ease}.waiting-room-footer .cancel-btn:hover{background:#f8f9fa;color:#212529}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse-active{0%,to{box-shadow:0 0 #1da4b166}50%{box-shadow:0 0 0 8px #1da4b100}}@keyframes pulse-ready{0%,to{box-shadow:0 2px 8px #1da4b140}50%{box-shadow:0 4px 16px #1da4b166}}@media (max-width: 576px){.tas-waiting-room{min-height:380px}.waiting-room-header{padding:24px 24px 20px}.waiting-room-header .header-icon{width:56px;height:56px}.waiting-room-header .header-icon i{font-size:22px}.waiting-room-header .header-title{font-size:18px}.waiting-room-content{padding:24px}.state-icon{width:64px;height:64px}.state-icon i{font-size:28px}.spinner{width:32px;height:32px}.progress-steps{gap:12px}.step .step-indicator{width:28px;height:28px}.step .step-label{font-size:9px}.action-btn{padding:10px 24px;font-size:14px}.waiting-room-footer{padding:16px 24px 20px}}\n"] }]
|
|
599
|
+
}], ctorParameters: function () { return [{ type: i1.NgbActiveModal }, { type: TasService }, { type: i1.NgbModal }]; }, propDecorators: { appointmentId: [{
|
|
600
|
+
type: Input
|
|
601
|
+
}], product: [{
|
|
602
|
+
type: Input
|
|
603
|
+
}], tenantId: [{
|
|
604
|
+
type: Input
|
|
605
|
+
}], currentUser: [{
|
|
606
|
+
type: Input
|
|
607
|
+
}], ownerUserIds: [{
|
|
608
|
+
type: Input
|
|
609
|
+
}], regularUserIds: [{
|
|
610
|
+
type: Input
|
|
611
|
+
}], moderatorUserIds: [{
|
|
612
|
+
type: Input
|
|
613
|
+
}] } });
|
|
614
|
+
|
|
615
|
+
class TasButtonComponent {
|
|
616
|
+
constructor(modalService, tasService) {
|
|
617
|
+
this.modalService = modalService;
|
|
618
|
+
this.tasService = tasService;
|
|
619
|
+
this.appointmentId = 1;
|
|
620
|
+
this.product = "uell";
|
|
621
|
+
this.tenantId = "";
|
|
622
|
+
this.regularUserIds = [];
|
|
623
|
+
this.moderatorUserIds = [];
|
|
624
|
+
this.isLoading = false;
|
|
625
|
+
this.subscriptions = new Subscription();
|
|
626
|
+
this.currentModalRef = null;
|
|
627
|
+
this.videoCallModalRef = null;
|
|
628
|
+
}
|
|
629
|
+
ngOnInit() {
|
|
630
|
+
if (!this.ownerUserIds || this.ownerUserIds.length !== 1) {
|
|
631
|
+
throw new Error('tas-btn: ownerUserIds input is required and must contain exactly one user');
|
|
632
|
+
}
|
|
633
|
+
// Subscribe to viewMode to handle PiP return
|
|
634
|
+
this.subscriptions.add(this.tasService.viewMode$.subscribe(mode => {
|
|
635
|
+
// Reopen video call modal when returning from PiP
|
|
636
|
+
if (mode === ViewMode.FULLSCREEN &&
|
|
637
|
+
this.tasService.isCallActive() &&
|
|
638
|
+
!this.videoCallModalRef) {
|
|
639
|
+
const sessionId = this.tasService.sessionId;
|
|
640
|
+
const token = this.tasService.token;
|
|
641
|
+
if (sessionId && token) {
|
|
642
|
+
this.openVideoCallModal(true);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
// When entering PiP, clear the videoCallModalRef since modal will close
|
|
646
|
+
if (mode === ViewMode.PIP) {
|
|
647
|
+
this.videoCallModalRef = null;
|
|
648
|
+
}
|
|
649
|
+
}));
|
|
650
|
+
}
|
|
651
|
+
ngOnDestroy() {
|
|
652
|
+
this.subscriptions.unsubscribe();
|
|
653
|
+
}
|
|
654
|
+
onClick() {
|
|
655
|
+
if (!this.tenantId || !this.currentUser?.name) {
|
|
656
|
+
console.error("Tenant ID or current user not available");
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
659
|
+
this.openWaitingRoomModal();
|
|
660
|
+
}
|
|
661
|
+
openWaitingRoomModal() {
|
|
662
|
+
this.currentModalRef = this.modalService.open(TasWaitingRoomComponent, {
|
|
663
|
+
size: "lg",
|
|
664
|
+
windowClass: "tas-waiting-room-modal",
|
|
524
665
|
backdrop: "static",
|
|
525
666
|
keyboard: false,
|
|
667
|
+
centered: true
|
|
526
668
|
});
|
|
527
|
-
|
|
528
|
-
this.currentModalRef.componentInstance.
|
|
529
|
-
this.currentModalRef.componentInstance.
|
|
530
|
-
|
|
531
|
-
this.currentModalRef.
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
669
|
+
// Pass all necessary inputs to the waiting room component
|
|
670
|
+
this.currentModalRef.componentInstance.appointmentId = this.appointmentId;
|
|
671
|
+
this.currentModalRef.componentInstance.product = this.product;
|
|
672
|
+
this.currentModalRef.componentInstance.tenantId = this.tenantId;
|
|
673
|
+
this.currentModalRef.componentInstance.currentUser = this.currentUser;
|
|
674
|
+
this.currentModalRef.componentInstance.ownerUserIds = this.ownerUserIds;
|
|
675
|
+
this.currentModalRef.componentInstance.regularUserIds = this.regularUserIds;
|
|
676
|
+
this.currentModalRef.componentInstance.moderatorUserIds = this.moderatorUserIds;
|
|
677
|
+
this.currentModalRef.result.then(() => { this.currentModalRef = null; }, () => { this.currentModalRef = null; });
|
|
678
|
+
}
|
|
679
|
+
openVideoCallModal(isReturningFromPip = false) {
|
|
680
|
+
this.videoCallModalRef = this.modalService.open(TasVideocallComponent, {
|
|
681
|
+
size: 'xl',
|
|
682
|
+
windowClass: 'tas-video-modal',
|
|
683
|
+
backdrop: 'static',
|
|
684
|
+
keyboard: false
|
|
535
685
|
});
|
|
686
|
+
this.videoCallModalRef.componentInstance.sessionId = this.tasService.sessionId;
|
|
687
|
+
this.videoCallModalRef.componentInstance.token = this.tasService.token;
|
|
688
|
+
this.videoCallModalRef.componentInstance.isReturningFromPip = isReturningFromPip;
|
|
689
|
+
this.videoCallModalRef.result.then(() => { this.videoCallModalRef = null; }, () => { this.videoCallModalRef = null; });
|
|
536
690
|
}
|
|
537
691
|
}
|
|
538
|
-
TasButtonComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TasButtonComponent, deps: [{ token:
|
|
539
|
-
TasButtonComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TasButtonComponent, selector: "tas-btn", ngImport: i0, template: "<button\n
|
|
692
|
+
TasButtonComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TasButtonComponent, deps: [{ token: i1.NgbModal }, { token: TasService }], target: i0.ɵɵFactoryTarget.Component });
|
|
693
|
+
TasButtonComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TasButtonComponent, selector: "tas-btn", inputs: { appointmentId: "appointmentId", product: "product", tenantId: "tenantId", currentUser: "currentUser", ownerUserIds: "ownerUserIds", regularUserIds: "regularUserIds", moderatorUserIds: "moderatorUserIds" }, ngImport: i0, template: "<button\n\ttype=\"button\"\n\tclass=\"btn btn-primary tas-btn\"\n\t(click)=\"onClick()\"\n\t[disabled]=\"isLoading\"\n>\n\t<i class=\"fa fa-video-camera\" aria-hidden=\"true\" *ngIf=\"!isLoading\"></i>\n\t<span *ngIf=\"!isLoading\"> Iniciar TAS</span>\n\t<span *ngIf=\"isLoading\"> Processing...</span>\n</button>\n\n", styles: [":host{display:inline-block}.tas-btn{background-color:#ee316b!important;color:#fff!important;border-color:#ee316b!important;margin-right:24px}.tas-btn:disabled{background-color:#ccc!important;border-color:#ccc!important;cursor:not-allowed}.tas-btn:hover:not(:disabled){background-color:#d62a5f!important;border-color:#d62a5f!important}.tas-btn i{margin-right:5px}\n"], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
540
694
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TasButtonComponent, decorators: [{
|
|
541
695
|
type: Component,
|
|
542
|
-
args: [{ selector: "tas-btn", template: "<button\n
|
|
543
|
-
}], ctorParameters: function () { return [{ type:
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
696
|
+
args: [{ selector: "tas-btn", template: "<button\n\ttype=\"button\"\n\tclass=\"btn btn-primary tas-btn\"\n\t(click)=\"onClick()\"\n\t[disabled]=\"isLoading\"\n>\n\t<i class=\"fa fa-video-camera\" aria-hidden=\"true\" *ngIf=\"!isLoading\"></i>\n\t<span *ngIf=\"!isLoading\"> Iniciar TAS</span>\n\t<span *ngIf=\"isLoading\"> Processing...</span>\n</button>\n\n", styles: [":host{display:inline-block}.tas-btn{background-color:#ee316b!important;color:#fff!important;border-color:#ee316b!important;margin-right:24px}.tas-btn:disabled{background-color:#ccc!important;border-color:#ccc!important;cursor:not-allowed}.tas-btn:hover:not(:disabled){background-color:#d62a5f!important;border-color:#d62a5f!important}.tas-btn i{margin-right:5px}\n"] }]
|
|
697
|
+
}], ctorParameters: function () { return [{ type: i1.NgbModal }, { type: TasService }]; }, propDecorators: { appointmentId: [{
|
|
698
|
+
type: Input
|
|
699
|
+
}], product: [{
|
|
700
|
+
type: Input
|
|
701
|
+
}], tenantId: [{
|
|
702
|
+
type: Input
|
|
703
|
+
}], currentUser: [{
|
|
704
|
+
type: Input
|
|
705
|
+
}], ownerUserIds: [{
|
|
706
|
+
type: Input
|
|
707
|
+
}], regularUserIds: [{
|
|
708
|
+
type: Input
|
|
709
|
+
}], moderatorUserIds: [{
|
|
710
|
+
type: Input
|
|
711
|
+
}] } });
|
|
549
712
|
|
|
550
713
|
class TasFloatingCallComponent {
|
|
551
714
|
constructor(tasService) {
|
|
@@ -553,13 +716,15 @@ class TasFloatingCallComponent {
|
|
|
553
716
|
this.isVisible = false;
|
|
554
717
|
this.isMuted = false;
|
|
555
718
|
this.subscriptions = new Subscription();
|
|
719
|
+
// Margin from screen edges (in pixels)
|
|
720
|
+
this.PIP_MARGIN = 20;
|
|
556
721
|
}
|
|
557
722
|
ngOnInit() {
|
|
558
723
|
this.setupSubscriptions();
|
|
559
724
|
}
|
|
560
725
|
ngOnDestroy() {
|
|
561
726
|
this.subscriptions.unsubscribe();
|
|
562
|
-
interact(
|
|
727
|
+
interact('.tas-floating-container').unset();
|
|
563
728
|
}
|
|
564
729
|
// Public Methods
|
|
565
730
|
onExpand() {
|
|
@@ -573,115 +738,171 @@ class TasFloatingCallComponent {
|
|
|
573
738
|
}
|
|
574
739
|
// Private Methods
|
|
575
740
|
setupSubscriptions() {
|
|
576
|
-
|
|
741
|
+
// Call state subscription
|
|
742
|
+
this.subscriptions.add(this.tasService.callState$.subscribe(state => {
|
|
577
743
|
if (state === CallState.DISCONNECTED) {
|
|
578
744
|
this.isVisible = false;
|
|
579
745
|
}
|
|
580
746
|
}));
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
747
|
+
// View mode subscription
|
|
748
|
+
this.subscriptions.add(this.tasService.viewMode$.subscribe(mode => {
|
|
749
|
+
this.isVisible = mode === ViewMode.PIP && this.tasService.isCallActive();
|
|
584
750
|
if (this.isVisible) {
|
|
585
751
|
setTimeout(() => this.initInteract(), 100);
|
|
586
752
|
}
|
|
587
753
|
}));
|
|
588
|
-
|
|
754
|
+
// Mute state subscription
|
|
755
|
+
this.subscriptions.add(this.tasService.isMuted$.subscribe(muted => {
|
|
589
756
|
this.isMuted = muted;
|
|
590
757
|
}));
|
|
591
758
|
}
|
|
592
759
|
initInteract() {
|
|
593
|
-
interact(
|
|
594
|
-
|
|
760
|
+
interact('.tas-floating-container').unset();
|
|
761
|
+
// Create restriction area with margin
|
|
762
|
+
const margin = this.PIP_MARGIN;
|
|
763
|
+
const restrictToBodyWithMargin = {
|
|
764
|
+
restriction: () => {
|
|
765
|
+
return {
|
|
766
|
+
left: margin,
|
|
767
|
+
top: margin,
|
|
768
|
+
right: window.innerWidth - margin,
|
|
769
|
+
bottom: window.innerHeight - margin
|
|
770
|
+
};
|
|
771
|
+
},
|
|
772
|
+
elementRect: { left: 0, right: 1, top: 0, bottom: 1 }
|
|
773
|
+
};
|
|
774
|
+
interact('.tas-floating-container')
|
|
775
|
+
.draggable({
|
|
595
776
|
inertia: true,
|
|
596
777
|
modifiers: [
|
|
597
|
-
interact.modifiers.
|
|
598
|
-
restriction: "body",
|
|
599
|
-
endOnly: true,
|
|
600
|
-
}),
|
|
778
|
+
interact.modifiers.restrict(restrictToBodyWithMargin)
|
|
601
779
|
],
|
|
602
780
|
autoScroll: false,
|
|
603
781
|
listeners: {
|
|
604
782
|
move: (event) => {
|
|
605
783
|
const target = event.target;
|
|
606
|
-
const x = (parseFloat(target.getAttribute(
|
|
607
|
-
const y = (parseFloat(target.getAttribute(
|
|
784
|
+
const x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx;
|
|
785
|
+
const y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
|
|
786
|
+
target.style.transform = `translate(${x}px, ${y}px)`;
|
|
787
|
+
target.setAttribute('data-x', String(x));
|
|
788
|
+
target.setAttribute('data-y', String(y));
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
})
|
|
792
|
+
.resizable({
|
|
793
|
+
edges: { left: false, right: true, bottom: true, top: false },
|
|
794
|
+
listeners: {
|
|
795
|
+
move: (event) => {
|
|
796
|
+
const target = event.target;
|
|
797
|
+
let x = parseFloat(target.getAttribute('data-x')) || 0;
|
|
798
|
+
let y = parseFloat(target.getAttribute('data-y')) || 0;
|
|
799
|
+
// Update element size
|
|
800
|
+
target.style.width = `${event.rect.width}px`;
|
|
801
|
+
target.style.height = `${event.rect.height}px`;
|
|
802
|
+
// Translate when resizing from top or left edges
|
|
803
|
+
x += event.deltaRect.left;
|
|
804
|
+
y += event.deltaRect.top;
|
|
608
805
|
target.style.transform = `translate(${x}px, ${y}px)`;
|
|
609
|
-
target.setAttribute(
|
|
610
|
-
target.setAttribute(
|
|
611
|
-
}
|
|
806
|
+
target.setAttribute('data-x', String(x));
|
|
807
|
+
target.setAttribute('data-y', String(y));
|
|
808
|
+
}
|
|
612
809
|
},
|
|
810
|
+
modifiers: [
|
|
811
|
+
interact.modifiers.restrictEdges({
|
|
812
|
+
outer: {
|
|
813
|
+
left: margin,
|
|
814
|
+
top: margin,
|
|
815
|
+
right: window.innerWidth - margin,
|
|
816
|
+
bottom: window.innerHeight - margin
|
|
817
|
+
}
|
|
818
|
+
}),
|
|
819
|
+
interact.modifiers.restrictSize({
|
|
820
|
+
min: { width: 200, height: 130 },
|
|
821
|
+
max: { width: 500, height: 350 }
|
|
822
|
+
}),
|
|
823
|
+
interact.modifiers.aspectRatio({ ratio: 'preserve' })
|
|
824
|
+
],
|
|
825
|
+
inertia: true
|
|
613
826
|
});
|
|
614
827
|
}
|
|
615
828
|
}
|
|
616
829
|
TasFloatingCallComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TasFloatingCallComponent, deps: [{ token: TasService }], target: i0.ɵɵFactoryTarget.Component });
|
|
617
|
-
TasFloatingCallComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TasFloatingCallComponent, selector: "tas-floating-call", ngImport: i0, template: "<div class=\"tas-floating-container\" [class.visible]=\"isVisible\">\n
|
|
830
|
+
TasFloatingCallComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TasFloatingCallComponent, selector: "tas-floating-call", ngImport: i0, template: "<div class=\"tas-floating-container\" [class.visible]=\"isVisible\">\n\t<!-- Video content area - shows main video only -->\n\t<div class=\"floating-content\">\n\t\t<!-- Main video container (subscriber if available, otherwise publisher) -->\n\t\t<div id=\"pip-main-video\" class=\"pip-main-video\"></div>\n\n\t\t<!-- Bottom controls -->\n\t\t<div class=\"floating-controls\">\n\t\t\t<button class=\"action-btn expand-btn\" (click)=\"onExpand()\" title=\"Expand to fullscreen\">\n\t\t\t\t<i class=\"fa fa-expand\"></i>\n\t\t\t</button>\n\t\t\t<button class=\"action-btn mute-btn\" [class.muted]=\"isMuted\" (click)=\"toggleMute()\" [title]=\"isMuted ? 'Unmute microphone' : 'Mute microphone'\">\n\t\t\t\t<i class=\"fa\" [class.fa-microphone]=\"!isMuted\" [class.fa-microphone-slash]=\"isMuted\"></i>\n\t\t\t</button>\n\t\t\t<button class=\"action-btn hangup-btn\" (click)=\"onHangUp()\" title=\"Hang up call\">\n\t\t\t\t<i class=\"fa fa-phone\" style=\"transform: rotate(135deg);\"></i>\n\t\t\t</button>\n\t\t</div>\n\t</div>\n</div>\n\n", styles: [".tas-floating-container{position:fixed;bottom:20px;right:20px;width:280px;height:180px;background:#000;border-radius:12px;box-shadow:0 8px 32px #00000080;z-index:9999;overflow:hidden;touch-action:none;-webkit-user-select:none;user-select:none;transition:opacity .3s ease,visibility .3s ease,box-shadow .2s ease;opacity:0;visibility:hidden;pointer-events:none}.tas-floating-container.visible{opacity:1;visibility:visible;pointer-events:auto}.tas-floating-container:hover{box-shadow:0 8px 32px #00000080,0 0 0 2px #ffffff4d}.floating-content{position:relative;width:100%;height:100%;overflow:hidden}.pip-main-video{position:absolute;top:0;left:0;width:100%;height:100%;background:#000}.pip-main-video ::ng-deep video{width:100%;height:100%;object-fit:cover}.pip-main-video ::ng-deep .OT_subscriber,.pip-main-video ::ng-deep .OT_publisher{width:100%!important;height:100%!important}.pip-main-video ::ng-deep .OT_edge-bar-item,.pip-main-video ::ng-deep .OT_mute,.pip-main-video ::ng-deep .OT_audio-level-meter,.pip-main-video ::ng-deep .OT_bar,.pip-main-video ::ng-deep .OT_name{display:none!important}.floating-controls{position:absolute;bottom:10px;left:50%;transform:translate(-50%);display:flex;gap:12px;padding:6px 14px;background:rgba(0,0,0,.7);border-radius:24px;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);opacity:0;visibility:hidden;transition:opacity .3s ease,visibility .3s ease}.tas-floating-container:hover .floating-controls{opacity:1;visibility:visible}.action-btn{width:32px;height:32px;border:none;border-radius:50%;cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:13px;transition:all .2s ease}.action-btn.expand-btn{background:rgba(255,255,255,.2);color:#fff}.action-btn.expand-btn:hover{background:rgba(255,255,255,.35);transform:scale(1.1)}.action-btn.mute-btn{background:rgba(255,255,255,.2);color:#fff}.action-btn.mute-btn:hover{background:rgba(255,255,255,.35);transform:scale(1.1)}.action-btn.mute-btn.muted{background:#f39c12;color:#fff}.action-btn.mute-btn.muted:hover{background:#e67e22}.action-btn.hangup-btn{background:#dc3545;color:#fff}.action-btn.hangup-btn:hover{background:#c82333;transform:scale(1.1)}\n"] });
|
|
618
831
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TasFloatingCallComponent, decorators: [{
|
|
619
832
|
type: Component,
|
|
620
|
-
args: [{ selector:
|
|
833
|
+
args: [{ selector: 'tas-floating-call', template: "<div class=\"tas-floating-container\" [class.visible]=\"isVisible\">\n\t<!-- Video content area - shows main video only -->\n\t<div class=\"floating-content\">\n\t\t<!-- Main video container (subscriber if available, otherwise publisher) -->\n\t\t<div id=\"pip-main-video\" class=\"pip-main-video\"></div>\n\n\t\t<!-- Bottom controls -->\n\t\t<div class=\"floating-controls\">\n\t\t\t<button class=\"action-btn expand-btn\" (click)=\"onExpand()\" title=\"Expand to fullscreen\">\n\t\t\t\t<i class=\"fa fa-expand\"></i>\n\t\t\t</button>\n\t\t\t<button class=\"action-btn mute-btn\" [class.muted]=\"isMuted\" (click)=\"toggleMute()\" [title]=\"isMuted ? 'Unmute microphone' : 'Mute microphone'\">\n\t\t\t\t<i class=\"fa\" [class.fa-microphone]=\"!isMuted\" [class.fa-microphone-slash]=\"isMuted\"></i>\n\t\t\t</button>\n\t\t\t<button class=\"action-btn hangup-btn\" (click)=\"onHangUp()\" title=\"Hang up call\">\n\t\t\t\t<i class=\"fa fa-phone\" style=\"transform: rotate(135deg);\"></i>\n\t\t\t</button>\n\t\t</div>\n\t</div>\n</div>\n\n", styles: [".tas-floating-container{position:fixed;bottom:20px;right:20px;width:280px;height:180px;background:#000;border-radius:12px;box-shadow:0 8px 32px #00000080;z-index:9999;overflow:hidden;touch-action:none;-webkit-user-select:none;user-select:none;transition:opacity .3s ease,visibility .3s ease,box-shadow .2s ease;opacity:0;visibility:hidden;pointer-events:none}.tas-floating-container.visible{opacity:1;visibility:visible;pointer-events:auto}.tas-floating-container:hover{box-shadow:0 8px 32px #00000080,0 0 0 2px #ffffff4d}.floating-content{position:relative;width:100%;height:100%;overflow:hidden}.pip-main-video{position:absolute;top:0;left:0;width:100%;height:100%;background:#000}.pip-main-video ::ng-deep video{width:100%;height:100%;object-fit:cover}.pip-main-video ::ng-deep .OT_subscriber,.pip-main-video ::ng-deep .OT_publisher{width:100%!important;height:100%!important}.pip-main-video ::ng-deep .OT_edge-bar-item,.pip-main-video ::ng-deep .OT_mute,.pip-main-video ::ng-deep .OT_audio-level-meter,.pip-main-video ::ng-deep .OT_bar,.pip-main-video ::ng-deep .OT_name{display:none!important}.floating-controls{position:absolute;bottom:10px;left:50%;transform:translate(-50%);display:flex;gap:12px;padding:6px 14px;background:rgba(0,0,0,.7);border-radius:24px;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);opacity:0;visibility:hidden;transition:opacity .3s ease,visibility .3s ease}.tas-floating-container:hover .floating-controls{opacity:1;visibility:visible}.action-btn{width:32px;height:32px;border:none;border-radius:50%;cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:13px;transition:all .2s ease}.action-btn.expand-btn{background:rgba(255,255,255,.2);color:#fff}.action-btn.expand-btn:hover{background:rgba(255,255,255,.35);transform:scale(1.1)}.action-btn.mute-btn{background:rgba(255,255,255,.2);color:#fff}.action-btn.mute-btn:hover{background:rgba(255,255,255,.35);transform:scale(1.1)}.action-btn.mute-btn.muted{background:#f39c12;color:#fff}.action-btn.mute-btn.muted:hover{background:#e67e22}.action-btn.hangup-btn{background:#dc3545;color:#fff}.action-btn.hangup-btn:hover{background:#c82333;transform:scale(1.1)}\n"] }]
|
|
621
834
|
}], ctorParameters: function () { return [{ type: TasService }]; } });
|
|
622
835
|
|
|
623
|
-
class
|
|
836
|
+
class TasUellSdkModule {
|
|
624
837
|
/**
|
|
625
|
-
* Use
|
|
838
|
+
* Use forRoot() to configure the TAS SDK module with required dependencies.
|
|
839
|
+
* This should only be called once in your root AppModule.
|
|
626
840
|
*
|
|
627
841
|
* @example
|
|
628
842
|
* ```typescript
|
|
629
|
-
*
|
|
630
|
-
*
|
|
631
|
-
*
|
|
632
|
-
*
|
|
633
|
-
*
|
|
634
|
-
*
|
|
635
|
-
*
|
|
843
|
+
* import { TasUellSdkModule, TasHttpClient } from 'tas-uell-sdk';
|
|
844
|
+
*
|
|
845
|
+
* // Create an adapter that implements TasHttpClient
|
|
846
|
+
* @Injectable({ providedIn: 'root' })
|
|
847
|
+
* export class MyHttpAdapter implements TasHttpClient {
|
|
848
|
+
* constructor(private http: HttpClient) {}
|
|
849
|
+
* post<T>(url: string, options: { body: any; headers?: Record<string, string> }): Observable<T> {
|
|
850
|
+
* return this.http.post<T>(url, options.body, { headers: options.headers });
|
|
851
|
+
* }
|
|
852
|
+
* }
|
|
853
|
+
*
|
|
854
|
+
* // In your AppModule
|
|
855
|
+
* @NgModule({
|
|
856
|
+
* imports: [
|
|
857
|
+
* TasUellSdkModule.forRoot({
|
|
858
|
+
* config: { tokBoxApiKey: 'YOUR_TOKBOX_API_KEY' },
|
|
859
|
+
* httpClient: MyHttpAdapter
|
|
860
|
+
* })
|
|
861
|
+
* ]
|
|
636
862
|
* })
|
|
863
|
+
* export class AppModule { }
|
|
637
864
|
* ```
|
|
638
865
|
*/
|
|
639
|
-
static forRoot(
|
|
640
|
-
const providers = [
|
|
641
|
-
{
|
|
642
|
-
provide: TAS_CONFIG,
|
|
643
|
-
useValue: moduleConfig.config,
|
|
644
|
-
},
|
|
645
|
-
];
|
|
646
|
-
if (moduleConfig.httpClient) {
|
|
647
|
-
providers.push({
|
|
648
|
-
provide: TAS_HTTP_CLIENT,
|
|
649
|
-
useClass: moduleConfig.httpClient,
|
|
650
|
-
});
|
|
651
|
-
}
|
|
652
|
-
if (moduleConfig.userDataProvider) {
|
|
653
|
-
providers.push({
|
|
654
|
-
provide: TAS_USER_DATA_PROVIDER,
|
|
655
|
-
useClass: moduleConfig.userDataProvider,
|
|
656
|
-
});
|
|
657
|
-
}
|
|
866
|
+
static forRoot(options) {
|
|
658
867
|
return {
|
|
659
|
-
ngModule:
|
|
660
|
-
providers
|
|
868
|
+
ngModule: TasUellSdkModule,
|
|
869
|
+
providers: [
|
|
870
|
+
{ provide: TAS_CONFIG, useValue: options.config },
|
|
871
|
+
{ provide: TAS_HTTP_CLIENT, useClass: options.httpClient },
|
|
872
|
+
TasService
|
|
873
|
+
]
|
|
661
874
|
};
|
|
662
875
|
}
|
|
663
876
|
}
|
|
664
|
-
|
|
665
|
-
|
|
877
|
+
TasUellSdkModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TasUellSdkModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
878
|
+
TasUellSdkModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TasUellSdkModule, declarations: [TasButtonComponent,
|
|
666
879
|
TasVideocallComponent,
|
|
667
|
-
TasFloatingCallComponent
|
|
880
|
+
TasFloatingCallComponent,
|
|
881
|
+
TasWaitingRoomComponent], imports: [CommonModule], exports: [TasButtonComponent,
|
|
668
882
|
TasVideocallComponent,
|
|
669
|
-
TasFloatingCallComponent
|
|
670
|
-
|
|
671
|
-
i0.ɵɵ
|
|
883
|
+
TasFloatingCallComponent,
|
|
884
|
+
TasWaitingRoomComponent] });
|
|
885
|
+
TasUellSdkModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TasUellSdkModule, imports: [[
|
|
886
|
+
CommonModule,
|
|
887
|
+
]] });
|
|
888
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TasUellSdkModule, decorators: [{
|
|
672
889
|
type: NgModule,
|
|
673
890
|
args: [{
|
|
674
891
|
declarations: [
|
|
675
892
|
TasButtonComponent,
|
|
676
893
|
TasVideocallComponent,
|
|
677
894
|
TasFloatingCallComponent,
|
|
895
|
+
TasWaitingRoomComponent
|
|
896
|
+
],
|
|
897
|
+
imports: [
|
|
898
|
+
CommonModule,
|
|
678
899
|
],
|
|
679
|
-
imports: [CommonModule, NgbModalModule],
|
|
680
900
|
exports: [
|
|
681
901
|
TasButtonComponent,
|
|
682
902
|
TasVideocallComponent,
|
|
683
903
|
TasFloatingCallComponent,
|
|
684
|
-
|
|
904
|
+
TasWaitingRoomComponent
|
|
905
|
+
]
|
|
685
906
|
}]
|
|
686
907
|
}] });
|
|
687
908
|
|
|
@@ -693,5 +914,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
693
914
|
* Generated bundle index. Do not edit.
|
|
694
915
|
*/
|
|
695
916
|
|
|
696
|
-
export { CallState, TAS_CONFIG, TAS_HTTP_CLIENT,
|
|
917
|
+
export { CallState, TAS_CONFIG, TAS_HTTP_CLIENT, TasButtonComponent, TasFloatingCallComponent, TasRoomType, TasService, TasSessionType, TasUellSdkModule, TasUserRole, TasVideocallComponent, TasWaitingRoomComponent, ViewMode, WaitingRoomState };
|
|
697
918
|
//# sourceMappingURL=tas-uell-sdk.mjs.map
|