@vgroup/dialbox 0.6.3-0.3 → 0.6.3-0.31
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/esm2020/lib/components/call-progress/call-progress.component.mjs +284 -649
- package/esm2020/lib/dialbox.component.mjs +19 -69
- package/esm2020/lib/dialbox.module.mjs +1 -1
- package/esm2020/public-api.mjs +1 -1
- package/fesm2015/vgroup-dialbox.mjs +287 -667
- package/fesm2015/vgroup-dialbox.mjs.map +1 -1
- package/fesm2020/vgroup-dialbox.mjs +301 -716
- package/fesm2020/vgroup-dialbox.mjs.map +1 -1
- package/lib/components/call-progress/call-progress.component.d.ts +9 -2
- package/lib/dialbox.component.d.ts +1 -0
- package/package.json +1 -1
|
@@ -1707,9 +1707,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
|
|
|
1707
1707
|
}] });
|
|
1708
1708
|
|
|
1709
1709
|
class CallProgressComponent {
|
|
1710
|
-
// audioURL:any = '/projects/dialbox/src/lib/shared/incoming_call.mp3';
|
|
1711
|
-
// /projects/dialbox/src/lib/shared/incoming_call.mp3
|
|
1712
|
-
// incomingAudio!: HTMLAudioElement;
|
|
1713
1710
|
constructor(extensionService, cdr, twilioService, ipService, incomeingCallSocketService) {
|
|
1714
1711
|
this.extensionService = extensionService;
|
|
1715
1712
|
this.cdr = cdr;
|
|
@@ -1735,7 +1732,6 @@ class CallProgressComponent {
|
|
|
1735
1732
|
this.isOutgoingCall = true;
|
|
1736
1733
|
// Incoming call variables
|
|
1737
1734
|
this.incomingCallDiv = false;
|
|
1738
|
-
//@Output() showCallProgressEvent: EventEmitter<void> = new EventEmitter<void>();
|
|
1739
1735
|
this.incomingCallInitiated = new EventEmitter();
|
|
1740
1736
|
this.isLoadershow = new EventEmitter();
|
|
1741
1737
|
this.endIncomingCallEvent = new EventEmitter();
|
|
@@ -1768,14 +1764,14 @@ class CallProgressComponent {
|
|
|
1768
1764
|
this.conferenceCallList = [];
|
|
1769
1765
|
this.isIncomingCallBtnDisable = false;
|
|
1770
1766
|
this.isNewAddedCall = false;
|
|
1767
|
+
this.deviceNumberList = [];
|
|
1768
|
+
this.ourNumberInfo = {};
|
|
1769
|
+
this.currentConferenceCall = {};
|
|
1771
1770
|
this.micOn = false;
|
|
1772
1771
|
this.isMinimised = false;
|
|
1772
|
+
this.showDisconnectModal = false;
|
|
1773
1773
|
console.log('Call Progress Component');
|
|
1774
1774
|
this.call = this.twilioService.call;
|
|
1775
|
-
// this.incomingAudio = this.createAudioFromBase64(
|
|
1776
|
-
// INCOMING_CALL_AUDIO_BASE64,
|
|
1777
|
-
// 'audio/mpeg' // use audio/wav if needed
|
|
1778
|
-
// );
|
|
1779
1775
|
}
|
|
1780
1776
|
ngOnInit() {
|
|
1781
1777
|
console.log('Call Progress Component ngOnInit');
|
|
@@ -1798,6 +1794,7 @@ class CallProgressComponent {
|
|
|
1798
1794
|
catch (e) {
|
|
1799
1795
|
console.error('Error subscribing to incoming calls:', e);
|
|
1800
1796
|
}
|
|
1797
|
+
this.deviceNumberList = this.callerIdList.map((res) => res.number);
|
|
1801
1798
|
this.GetContactsList();
|
|
1802
1799
|
}
|
|
1803
1800
|
ngOnChanges(changes) {
|
|
@@ -1831,100 +1828,75 @@ class CallProgressComponent {
|
|
|
1831
1828
|
}
|
|
1832
1829
|
if (changes['newIncomingCallsList']?.currentValue) {
|
|
1833
1830
|
if (this.newIncomingCallsList?.length) {
|
|
1834
|
-
|
|
1831
|
+
if (!this.deviceNumberList?.length) {
|
|
1832
|
+
this.deviceNumberList = this.callerIdList.map((res) => res.number);
|
|
1833
|
+
}
|
|
1835
1834
|
this.newIncomingCallsList.forEach((callInfo, i) => {
|
|
1836
1835
|
this.conferenceId = i == 0 ? this.newIncomingCallsList[i].conferenceId : this.conferenceId;
|
|
1837
|
-
let
|
|
1838
|
-
if (
|
|
1836
|
+
let ourNumberInfo = this.newIncomingCallsList[i].participants.find((resData) => ((this.deviceNumberList.includes(resData?.from) && resData?.to == 'c2c_softphone_client') || (this.deviceNumberList.includes(resData?.to) && resData?.direction == 'incoming-call')) && !resData?.isLeft);
|
|
1837
|
+
if (ourNumberInfo?.id) {
|
|
1839
1838
|
this.newIncomingCallsList[i].participants.forEach(async (res) => {
|
|
1840
|
-
if (res?.to == 'c2c_softphone_client'
|
|
1839
|
+
if (res?.to == 'c2c_softphone_client') {
|
|
1841
1840
|
this.hostnumber = res;
|
|
1842
1841
|
}
|
|
1843
1842
|
else {
|
|
1844
1843
|
let contact = {};
|
|
1845
1844
|
if (this.contacts?.length) {
|
|
1846
|
-
contact = this.contacts.find((resData) => resData?.numbersList[0]?.number == (res
|
|
1845
|
+
contact = this.contacts.find((resData) => resData?.numbersList[0]?.number == (res?.direction == "incoming-call" ? res?.from : res?.to));
|
|
1847
1846
|
}
|
|
1848
|
-
if (this.currentCallList
|
|
1849
|
-
let index = this.currentCallList.findIndex((item) => item
|
|
1847
|
+
if (this.currentCallList?.length > 0) {
|
|
1848
|
+
let index = this.currentCallList.findIndex((item) => item?.id == res?.id);
|
|
1850
1849
|
if (index == -1 && !res.isLeft) {
|
|
1851
1850
|
this.currentCallList.push({
|
|
1852
1851
|
...res,
|
|
1853
|
-
img: res
|
|
1854
|
-
isIncomingCall: res
|
|
1855
|
-
isHold: res
|
|
1852
|
+
img: res?.direction == "incoming-call" ? res?.toImage : res?.fromImage || contact?.image || 'assets/images/user.jpg',
|
|
1853
|
+
isIncomingCall: res?.direction == "incoming-call",
|
|
1854
|
+
isHold: res?.isHold,
|
|
1855
|
+
isConferenceHold: ourNumberInfo?.isHold || false,
|
|
1856
1856
|
isMute: false,
|
|
1857
|
-
isConference: res
|
|
1858
|
-
isAcceptCall: res
|
|
1857
|
+
isConference: res?.isConference,
|
|
1858
|
+
isAcceptCall: res?.direction == "incoming-call" ? this.getStatus(res) : true,
|
|
1859
1859
|
dial: true,
|
|
1860
|
-
phone: res
|
|
1861
|
-
participantId: res
|
|
1862
|
-
conferenceSid: callInfo
|
|
1863
|
-
name: res
|
|
1864
|
-
time: this.getTimeDifference(res
|
|
1860
|
+
phone: res?.direction == "incoming-call" ? res?.from : res?.to,
|
|
1861
|
+
participantId: res?.id,
|
|
1862
|
+
conferenceSid: callInfo?.conferenceSid,
|
|
1863
|
+
name: res?.name || res?.fromName || res?.toName,
|
|
1864
|
+
time: this.getTimeDifference(res?.joinedAt || new Date().toUTCString()),
|
|
1865
1865
|
});
|
|
1866
1866
|
if (this.showContactsPanel) {
|
|
1867
|
-
this.getAllParticipants(this.currentCall
|
|
1867
|
+
this.getAllParticipants(this.currentCall?.conferenceSid);
|
|
1868
1868
|
this.applyFilter();
|
|
1869
1869
|
}
|
|
1870
1870
|
}
|
|
1871
|
-
else if (index != -1 && res
|
|
1871
|
+
else if (index != -1 && res?.isLeft) {
|
|
1872
1872
|
if (this.currentCallList[index]?.id == this.currentCall?.id) {
|
|
1873
1873
|
this.currentCallList.splice(index, 1);
|
|
1874
|
-
this.currentCall = this.currentCallList
|
|
1875
|
-
if (this.currentCall?.isHold && !this.currentCall?.isConference) {
|
|
1876
|
-
await this.onholdOrUnholdParticipant({
|
|
1877
|
-
participantId: [this.currentCall?.participantId],
|
|
1878
|
-
conferenceId: this.currentCall?.conferenceId,
|
|
1879
|
-
hold: false,
|
|
1880
|
-
mute: this.currentCall?.mute || false,
|
|
1881
|
-
conference: this.currentCall?.isConference
|
|
1882
|
-
});
|
|
1883
|
-
}
|
|
1884
|
-
else if (this.currentCall?.isHold && this.currentCall?.isConference) {
|
|
1885
|
-
let conferenceCalllist = this.currentCallList.filter((item) => item.isConference && item.conferenceId == this.currentCall?.conferenceId);
|
|
1886
|
-
if (conferenceCalllist.length > 0) {
|
|
1887
|
-
// await this.onholdOrUnholdParticipant({
|
|
1888
|
-
// participantId: conferenceCalllist.map((item: any) => item.participantId),
|
|
1889
|
-
// conferenceId: conferenceCalllist[0]?.conferenceId,
|
|
1890
|
-
// hold: false,
|
|
1891
|
-
// mute: this.currentCall?.mute || false,
|
|
1892
|
-
// conference: this.currentCall?.isConference || false
|
|
1893
|
-
// });
|
|
1894
|
-
await this.onholdOrUnholdParticipant({
|
|
1895
|
-
participantId: [this.hostnumber?.participantId],
|
|
1896
|
-
conferenceId: this.currentCall?.conferenceId,
|
|
1897
|
-
hold: false,
|
|
1898
|
-
mute: this.currentCall?.mute || false,
|
|
1899
|
-
conference: this.currentCall?.isConference
|
|
1900
|
-
});
|
|
1901
|
-
this.isConferenceCallHold = false;
|
|
1902
|
-
}
|
|
1903
|
-
}
|
|
1874
|
+
this.currentCall = this.currentCallList?.length > 0 ? this.currentCallList[0] : {};
|
|
1904
1875
|
}
|
|
1905
1876
|
else {
|
|
1906
1877
|
this.currentCallList.splice(index, 1);
|
|
1907
1878
|
}
|
|
1908
1879
|
if (this.showContactsPanel) {
|
|
1909
|
-
this.getAllParticipants(this.currentCall
|
|
1880
|
+
this.getAllParticipants(this.currentCall?.conferenceSid);
|
|
1910
1881
|
this.applyFilter();
|
|
1911
1882
|
}
|
|
1912
1883
|
}
|
|
1913
1884
|
else if (index != -1) {
|
|
1914
1885
|
this.currentCallList[index] = {
|
|
1915
1886
|
...res,
|
|
1916
|
-
img: res
|
|
1917
|
-
isIncomingCall: res
|
|
1918
|
-
isHold: res
|
|
1919
|
-
|
|
1920
|
-
|
|
1887
|
+
img: res?.direction == "incoming-call" ? res?.toImage : res?.fromImage || contact?.image || 'assets/images/user.jpg',
|
|
1888
|
+
isIncomingCall: res?.direction == "incoming-call",
|
|
1889
|
+
isHold: res?.isHold,
|
|
1890
|
+
isConferenceHold: ourNumberInfo?.isHold || false,
|
|
1891
|
+
isMute: res?.isMute,
|
|
1892
|
+
isConference: res?.isConference,
|
|
1921
1893
|
isAcceptCall: res.direction == "incoming-call" ? this.getStatus(res) : true,
|
|
1922
1894
|
dial: true,
|
|
1923
|
-
phone: res
|
|
1924
|
-
participantId: res
|
|
1925
|
-
conferenceSid: callInfo
|
|
1926
|
-
name: res
|
|
1927
|
-
time: this.getTimeDifference(res
|
|
1895
|
+
phone: res?.direction == "incoming-call" ? res?.from : res?.to,
|
|
1896
|
+
participantId: res?.id,
|
|
1897
|
+
conferenceSid: callInfo?.conferenceSid,
|
|
1898
|
+
name: res?.name || res?.fromName || res?.toName,
|
|
1899
|
+
time: this.getTimeDifference(res?.joinedAt || new Date().toUTCString()),
|
|
1928
1900
|
};
|
|
1929
1901
|
}
|
|
1930
1902
|
}
|
|
@@ -1933,16 +1905,17 @@ class CallProgressComponent {
|
|
|
1933
1905
|
...res,
|
|
1934
1906
|
img: res.direction == "incoming-call" ? res?.toImage : res?.fromImage || contact?.image || 'assets/images/user.jpg',
|
|
1935
1907
|
isIncomingCall: res.direction == "incoming-call",
|
|
1936
|
-
isHold: res
|
|
1937
|
-
|
|
1908
|
+
isHold: res?.isHold,
|
|
1909
|
+
isConferenceHold: ourNumberInfo?.isHold || false,
|
|
1910
|
+
isMute: res?.isMute,
|
|
1938
1911
|
isConference: res.isConference,
|
|
1939
1912
|
isAcceptCall: res.direction == "incoming-call" ? this.getStatus(res) : true,
|
|
1940
1913
|
dial: true,
|
|
1941
1914
|
phone: res.direction == "incoming-call" ? res?.from : res?.to,
|
|
1942
1915
|
participantId: res.id,
|
|
1943
|
-
conferenceSid: callInfo
|
|
1944
|
-
name: res
|
|
1945
|
-
time: this.getTimeDifference(res
|
|
1916
|
+
conferenceSid: callInfo?.conferenceSid,
|
|
1917
|
+
name: res?.name || res?.fromName || res?.toName,
|
|
1918
|
+
time: this.getTimeDifference(res?.joinedAt || new Date().toUTCString()),
|
|
1946
1919
|
});
|
|
1947
1920
|
if (this.currentCallList?.length == 1) {
|
|
1948
1921
|
this.currentCall = this.currentCallList[0];
|
|
@@ -1977,8 +1950,11 @@ class CallProgressComponent {
|
|
|
1977
1950
|
});
|
|
1978
1951
|
let validValues = new Set(this.newIncomingCallsList.flatMap((item) => item?.participants.map((val) => val?.id)));
|
|
1979
1952
|
this.currentCallList = this.currentCallList.filter((item) => validValues.has(item?.participantId));
|
|
1980
|
-
this.currentCall = this.currentCallList.find((res) => this.currentCall?.participantId == res?.participantId);
|
|
1981
|
-
let currentCall = this.currentCallList.filter((item) => item?.isAcceptCall && !item?.
|
|
1953
|
+
this.currentCall = this.currentCallList.find((res) => this.currentCall?.participantId == res?.participantId && !res?.isConferenceHold);
|
|
1954
|
+
let currentCall = this.currentCallList.filter((item) => item?.isAcceptCall && !item?.isConferenceHold);
|
|
1955
|
+
this.currentConferenceCall = this.newIncomingCallsList.find((item) => {
|
|
1956
|
+
return ((this.deviceNumberList.includes(item?.from) && item?.to === 'c2c_softphone_client') || this.deviceNumberList.includes(item?.to)) && !item?.isLeft && !item?.isHold;
|
|
1957
|
+
});
|
|
1982
1958
|
if (currentCall?.length == 1 && currentCall[0]?.id) {
|
|
1983
1959
|
this.currentCall = currentCall[0] || this.currentCallList[0];
|
|
1984
1960
|
}
|
|
@@ -1986,71 +1962,64 @@ class CallProgressComponent {
|
|
|
1986
1962
|
this.currentCall = currentCall[0] || this.currentCallList[0];
|
|
1987
1963
|
this.isConference = true;
|
|
1988
1964
|
}
|
|
1989
|
-
if (!this.
|
|
1990
|
-
this.
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
1965
|
+
if (!this.currentConferenceCall && !this.isNewAddedCall) {
|
|
1966
|
+
// this.currentConferenceCall = this.newIncomingCallsList.find((item: any) => {
|
|
1967
|
+
// return ((this.deviceNumberList.includes(item?.from) && item?.to === 'c2c_softphone_client') || this.deviceNumberList.includes(item?.to)) && !item?.isLeft && !item?.isHold
|
|
1968
|
+
// });
|
|
1969
|
+
// this.currentCall = this.currentCallList.find((res: any) => res?.participantId == this.currentCall?.participantId && res?.isAcceptCall && !res?.isConferenceHold)
|
|
1970
|
+
// if (!this.currentConferenceCall?.id && this.currentCallList?.length) {
|
|
1971
|
+
// this.currentConferenceCall = this.newIncomingCallsList.find((item: any) => {
|
|
1972
|
+
// return ((this.deviceNumberList.includes(item?.from) && item?.to === 'c2c_softphone_client') || this.deviceNumberList.includes(item?.to)) && !item?.isLeft && item?.isHold
|
|
1973
|
+
// });
|
|
1974
|
+
// let calldetail = this.currentConferenceCall.find((resInfo: any) => ((this.deviceNumberList.includes(resInfo?.from) && resInfo?.to === 'c2c_softphone_client') || this.deviceNumberList.includes(resInfo?.to)) && !resInfo?.isLeft && resInfo?.isHold)
|
|
1975
|
+
// if (calldetail?.isHold) {
|
|
1976
|
+
// this.isConference = true;
|
|
1977
|
+
// this.onholdOrUnholdParticipant({
|
|
1978
|
+
// participantId: [calldetail?.id || calldetail?.participantId],
|
|
1979
|
+
// conferenceId: calldetail?.conferenceId,
|
|
1980
|
+
// hold: false,
|
|
1981
|
+
// mute: calldetail?.mute || false,
|
|
1982
|
+
// conference: calldetail?.isConference || false
|
|
1983
|
+
// });
|
|
1984
|
+
// }
|
|
1985
|
+
// }
|
|
1986
|
+
// if (!this.currentCall?.participantId) {
|
|
1987
|
+
// this.currentCall = this.currentCallList[0];
|
|
1988
|
+
// if (this.currentCallList[0]?.isConferenceHold && this.currentCallList[0]?.isConference) {
|
|
1989
|
+
// this.isConference = true;
|
|
1990
|
+
// this.onholdOrUnholdParticipant({
|
|
1991
|
+
// participantId: [this.currentCall?.participantId],
|
|
1992
|
+
// conferenceId: this.currentCall?.conferenceId,
|
|
1993
|
+
// hold: false,
|
|
1994
|
+
// mute: this.currentCall?.mute || false,
|
|
1995
|
+
// conference: this.currentCall?.isConference || false
|
|
1996
|
+
// });
|
|
1997
|
+
// } else if (this.currentCall?.isConferenceHold) {
|
|
1998
|
+
// this.onholdOrUnholdParticipant({
|
|
1999
|
+
// participantId: [this.currentCall?.participantId],
|
|
2000
|
+
// conferenceId: this.currentCall?.conferenceId,
|
|
2001
|
+
// hold: false,
|
|
2002
|
+
// mute: this.currentCall?.mute || false,
|
|
2003
|
+
// conference: this.currentCall?.isConference || false
|
|
2004
|
+
// });
|
|
2005
|
+
// }
|
|
2006
|
+
// }
|
|
2007
|
+
let currentConferenceCallInfo = this.getCurrentCallInfo();
|
|
2008
|
+
if (!currentConferenceCallInfo?.id) {
|
|
2009
|
+
let holdCallInfo = this.newIncomingCallsList[0].participants.find((callInfo) => ((this.deviceNumberList.includes(callInfo?.from) && callInfo?.to === 'c2c_softphone_client')
|
|
2010
|
+
|| this.deviceNumberList.includes(callInfo?.to)) && !callInfo?.isLeft && callInfo?.isHold);
|
|
2011
|
+
if (holdCallInfo?.id) {
|
|
2015
2012
|
this.onholdOrUnholdParticipant({
|
|
2016
|
-
participantId: [
|
|
2017
|
-
conferenceId:
|
|
2013
|
+
participantId: [holdCallInfo?.id],
|
|
2014
|
+
conferenceId: holdCallInfo?.conferenceId,
|
|
2018
2015
|
hold: false,
|
|
2019
|
-
mute:
|
|
2020
|
-
conference:
|
|
2016
|
+
mute: holdCallInfo?.mute || false,
|
|
2017
|
+
conference: holdCallInfo?.isConference || false
|
|
2021
2018
|
});
|
|
2022
2019
|
}
|
|
2023
2020
|
}
|
|
2024
2021
|
}
|
|
2025
|
-
|
|
2026
|
-
// this.currentCall = this.currentCallList.find((res: any)=> res?.participantId == this.currentCall?.participantId && res?.isAcceptCall && !res?.isHold)
|
|
2027
|
-
// if(!this.currentCall?.participantId) {
|
|
2028
|
-
// this.currentCall = this.currentCallList[0];
|
|
2029
|
-
// if(this.currentCallList[0].isHold && this.currentCallList[0]?.isConference) {
|
|
2030
|
-
// this.isConference = true;
|
|
2031
|
-
// this.currentCallList.forEach((res) => {
|
|
2032
|
-
// if (res.isConference && this.currentCall?.participantId) {
|
|
2033
|
-
// this.onholdOrUnholdParticipant({
|
|
2034
|
-
// participantId: [res.participantId],
|
|
2035
|
-
// conferenceId: res?.conferenceId,
|
|
2036
|
-
// hold: false,
|
|
2037
|
-
// mute: res?.mute || false,
|
|
2038
|
-
// conference: res?.isConference || false
|
|
2039
|
-
// });
|
|
2040
|
-
// }
|
|
2041
|
-
// })
|
|
2042
|
-
// } else {
|
|
2043
|
-
// this.onholdOrUnholdParticipant({
|
|
2044
|
-
// participantId: [this.currentCall?.participantId],
|
|
2045
|
-
// conferenceId: this.currentCall?.conferenceId,
|
|
2046
|
-
// hold: false,
|
|
2047
|
-
// mute: this.currentCall?.mute || false,
|
|
2048
|
-
// conference: this.currentCall?.isConference || false
|
|
2049
|
-
// });
|
|
2050
|
-
// }
|
|
2051
|
-
// }
|
|
2052
|
-
// } else {
|
|
2053
|
-
// }
|
|
2022
|
+
console.log(this.currentConferenceCall, 'currentConferenceCall');
|
|
2054
2023
|
console.log(this.leftParticipent, 'leftParticipent');
|
|
2055
2024
|
if (this.selectedUserInfo?.participantId) {
|
|
2056
2025
|
let selectedUser = this.currentCallList.find((item) => item?.id == this.selectedUserInfo?.participantId);
|
|
@@ -2279,25 +2248,25 @@ class CallProgressComponent {
|
|
|
2279
2248
|
});
|
|
2280
2249
|
}
|
|
2281
2250
|
async onEndCall(c, isAllCallEnd, isContect) {
|
|
2282
|
-
if (!c?.isAcceptCall && !isContect && !isAllCallEnd) {
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
}
|
|
2293
|
-
let participantId = isAllCallEnd ? 'all' : c.participantId;
|
|
2294
|
-
|
|
2251
|
+
// if (!c?.isAcceptCall && !isContect && !isAllCallEnd) {
|
|
2252
|
+
// let index = this.currentCallList.findIndex((res) => res.participantId == c.participantId)
|
|
2253
|
+
// await this.extensionService.getRemoveParticipants(this.currentCallList[index]?.participantId, this.currentCallList[index]?.conferenceId || 'no').subscribe((res) => {
|
|
2254
|
+
// this.currentCallList.splice(index, 1)
|
|
2255
|
+
// this.incomeingCallSocketService.pause();
|
|
2256
|
+
// this.call?.disconnect();
|
|
2257
|
+
// this.endIncomingCallEvent.emit(c);
|
|
2258
|
+
// return false;
|
|
2259
|
+
// })
|
|
2260
|
+
// return false;
|
|
2261
|
+
// }
|
|
2262
|
+
let participantId = isAllCallEnd ? 'all' : c.participantId || c?.id;
|
|
2263
|
+
const currentConferenceCallInfo = this.getCurrentCallInfo();
|
|
2264
|
+
let conferenceId = c.conferenceId || currentConferenceCallInfo?.conferenceId;
|
|
2295
2265
|
let res = await this.getRemoveParticipants(participantId, conferenceId);
|
|
2296
2266
|
if (res?.status == 201 && res?.message == 'participant already left') {
|
|
2297
2267
|
this.cdr.detectChanges();
|
|
2298
2268
|
}
|
|
2299
|
-
await this.getAllParticipants(
|
|
2300
|
-
this.currentCallList = this.currentCallList.filter((res) => res.participantId !== c.participantId);
|
|
2269
|
+
await this.getAllParticipants(conferenceId);
|
|
2301
2270
|
this.incomeingCallSocketService.pause();
|
|
2302
2271
|
this.endIncomingCallEvent.emit(c);
|
|
2303
2272
|
this.cdr.detectChanges();
|
|
@@ -2392,15 +2361,6 @@ class CallProgressComponent {
|
|
|
2392
2361
|
catch (e) {
|
|
2393
2362
|
console.log('Error updating accept state:', e);
|
|
2394
2363
|
}
|
|
2395
|
-
// Start recording if recordCall is true and call is accepted for 30 seconds
|
|
2396
|
-
// if (this.recordCall) {
|
|
2397
|
-
// setTimeout(() => {
|
|
2398
|
-
// if (this.isRecording) return; // If already recording, skip
|
|
2399
|
-
// this.startRecording();
|
|
2400
|
-
// }, 30000);
|
|
2401
|
-
// } else {
|
|
2402
|
-
// this.stopRecording();
|
|
2403
|
-
// }
|
|
2404
2364
|
});
|
|
2405
2365
|
this.call?.on('messageReceived', (message) => {
|
|
2406
2366
|
});
|
|
@@ -2428,145 +2388,47 @@ class CallProgressComponent {
|
|
|
2428
2388
|
handleError(error) {
|
|
2429
2389
|
swal("Error", error, "error");
|
|
2430
2390
|
}
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
// }
|
|
2440
|
-
// this.showRingAnimation = false;
|
|
2441
|
-
// this.stopTimer();
|
|
2442
|
-
// // If there's a held call, make it active
|
|
2443
|
-
// if (this.heldCall) {
|
|
2444
|
-
// console.log('Resuming held call:', this.heldCall.parameters['From']);
|
|
2445
|
-
// // Make held call the active call
|
|
2446
|
-
// this.call = this.heldCall;
|
|
2447
|
-
// this.heldCall = undefined;
|
|
2448
|
-
// // this.isCallOnHold = false;
|
|
2449
|
-
// this.isCallOnHold = !!this.heldCall;
|
|
2450
|
-
// // Unmute the resumed call
|
|
2451
|
-
// this.call.mute(false);
|
|
2452
|
-
// // Update UI with the resumed call info
|
|
2453
|
-
// const fromNumber = this.call.parameters['From'];
|
|
2454
|
-
// const callerName = this.call.customParameters?.get('name') || '-';
|
|
2455
|
-
// const callerImg = this.call.customParameters?.get('image') || 'assets/images/user.jpg';
|
|
2456
|
-
// this.callData = {
|
|
2457
|
-
// ...this.callData,
|
|
2458
|
-
// phone: fromNumber,
|
|
2459
|
-
// displayNum: fromNumber,
|
|
2460
|
-
// name: callerName,
|
|
2461
|
-
// img: callerImg
|
|
2462
|
-
// };
|
|
2463
|
-
// // Restart timer for the resumed call
|
|
2464
|
-
// this.startTimer();
|
|
2465
|
-
// this.disbaleEndCallBtn = false;
|
|
2466
|
-
// console.log('Held call is now active:', this.callData);
|
|
2467
|
-
// this.cdr.detectChanges();
|
|
2468
|
-
// } else {
|
|
2469
|
-
// // No held call, completely end
|
|
2470
|
-
// console.log('No held call, ending completely');
|
|
2471
|
-
// this.endCallEvent.emit();
|
|
2472
|
-
// this.maximiseDialpad();
|
|
2473
|
-
// }
|
|
2474
|
-
// }
|
|
2391
|
+
endConfereneceCall() {
|
|
2392
|
+
if (this.deviceNumberList.includes(this.hostnumber?.from)) {
|
|
2393
|
+
this.onCallDisconnected();
|
|
2394
|
+
}
|
|
2395
|
+
else {
|
|
2396
|
+
this.endCall();
|
|
2397
|
+
}
|
|
2398
|
+
}
|
|
2475
2399
|
async endCall(isAllCallEnd) {
|
|
2476
2400
|
console.log('endCall() called');
|
|
2477
|
-
// console.log('Current call:', this.call?.parameters['From']);
|
|
2478
2401
|
console.log('Held call exists:', !!this.heldCall);
|
|
2479
|
-
// Leaving conference state when ending current call action
|
|
2480
2402
|
this.isConference = false;
|
|
2481
2403
|
this.showRingAnimation = false;
|
|
2482
2404
|
if (isAllCallEnd) {
|
|
2483
2405
|
this.stopTimer();
|
|
2484
2406
|
this.onEndCall({}, isAllCallEnd);
|
|
2485
|
-
// this.currentCallList = [];
|
|
2486
2407
|
if (!this.currentCallList?.length) {
|
|
2487
2408
|
this.endCallEvent.emit();
|
|
2488
2409
|
}
|
|
2489
2410
|
}
|
|
2490
2411
|
else {
|
|
2491
|
-
this.
|
|
2492
|
-
this.
|
|
2493
|
-
if (this.currentCallList.length > 0) {
|
|
2494
|
-
// this.currentCallList[0].isHold = false;
|
|
2495
|
-
// this.currentCall = this.currentCallList[0];
|
|
2496
|
-
await this.onholdOrUnholdParticipant({
|
|
2497
|
-
participantId: [this.currentCall?.participantId],
|
|
2498
|
-
conferenceId: this.currentCall?.conferenceId,
|
|
2499
|
-
hold: false,
|
|
2500
|
-
mute: this.currentCall?.mute || false,
|
|
2501
|
-
isConference: this.currentCall?.isConference || false
|
|
2502
|
-
});
|
|
2503
|
-
}
|
|
2504
|
-
else {
|
|
2505
|
-
// this.currentCall = null;
|
|
2506
|
-
// this.currentCallList = [];
|
|
2507
|
-
this.endCallEvent.emit();
|
|
2508
|
-
}
|
|
2412
|
+
const currentConferenceCallInfo = this.getCurrentCallInfo();
|
|
2413
|
+
this.onEndCall(currentConferenceCallInfo, isAllCallEnd);
|
|
2509
2414
|
}
|
|
2510
2415
|
if (this.call) {
|
|
2511
2416
|
this.call.disconnect();
|
|
2512
2417
|
this.call.reject();
|
|
2513
|
-
// this.call = undefined;
|
|
2514
2418
|
}
|
|
2515
|
-
// if (this.heldCall) {
|
|
2516
|
-
// if (this.call) {
|
|
2517
|
-
// // this.call.disconnect();
|
|
2518
|
-
// // this.call = undefined;
|
|
2519
|
-
// this.onEndCall(this.call?.callInfo, isAllCallEnd);
|
|
2520
|
-
// }
|
|
2521
|
-
// console.log('Resuming held call:', this.heldCall.parameters['From']);
|
|
2522
|
-
// // Promote held call
|
|
2523
|
-
// // this.call = this.heldCall;
|
|
2524
|
-
// this.heldCall = undefined;
|
|
2525
|
-
// // this.isCallOnHold = false;
|
|
2526
|
-
// // this.incomingCallDiv = false; // Ensure UI renders
|
|
2527
|
-
// // this.call.mute(false);
|
|
2528
|
-
// // Update callData
|
|
2529
|
-
// const fromNumber = this.call.parameters['From'];
|
|
2530
|
-
// const callerName = this.call.customParameters?.get('name') || '-';
|
|
2531
|
-
// const callerImg = this.call.customParameters?.get('image') || 'assets/images/user.jpg';
|
|
2532
|
-
// this.callData = {
|
|
2533
|
-
// phone: fromNumber,
|
|
2534
|
-
// displayNum: fromNumber,
|
|
2535
|
-
// name: callerName,
|
|
2536
|
-
// img: callerImg
|
|
2537
|
-
// };
|
|
2538
|
-
// this.startTimer();
|
|
2539
|
-
// this.disbaleEndCallBtn = false;
|
|
2540
|
-
// // Force UI update
|
|
2541
|
-
// setTimeout(() => this.cdr.detectChanges());
|
|
2542
|
-
// console.log('Held call is now active:', this.callData);
|
|
2543
|
-
// } else {
|
|
2544
|
-
// console.log('No held call, ending completely');
|
|
2545
|
-
// console.log('test6')
|
|
2546
|
-
// this.endCallEvent.emit();
|
|
2547
|
-
// if (this.call) {
|
|
2548
|
-
// this.call.disconnect();
|
|
2549
|
-
// this.onEndCall(this.call?.callInfo, isAllCallEnd);
|
|
2550
|
-
// // this.call = undefined;
|
|
2551
|
-
// }
|
|
2552
|
-
// this.maximiseDialpad();
|
|
2553
|
-
// }
|
|
2554
2419
|
}
|
|
2555
2420
|
async toggleMute(isConference) {
|
|
2556
|
-
// await this.onMuteParticipant({
|
|
2557
|
-
// participantId: [this.currentCall?.participantId],
|
|
2558
|
-
// conferenceId: this.conferenceId,
|
|
2559
|
-
// mute: !this.isMute,
|
|
2560
|
-
// })
|
|
2561
|
-
// this.call = this.heldCall
|
|
2562
|
-
// this.toggleMic()
|
|
2563
2421
|
this.isMute = !this.isMute;
|
|
2564
|
-
console.log('isMute', this.call, this.heldCall);
|
|
2565
2422
|
this.call?.mute(this.isMute);
|
|
2566
|
-
|
|
2423
|
+
const currentConferenceCallInfo = this.getCurrentCallInfo();
|
|
2424
|
+
this.onMuteParticipant({
|
|
2425
|
+
participantId: [currentConferenceCallInfo.participantId || currentConferenceCallInfo?.id],
|
|
2426
|
+
conferenceId: currentConferenceCallInfo?.conferenceId,
|
|
2427
|
+
hold: currentConferenceCallInfo.hold,
|
|
2428
|
+
mute: !currentConferenceCallInfo?.isMute,
|
|
2429
|
+
conference: currentConferenceCallInfo.isConference || false
|
|
2430
|
+
});
|
|
2567
2431
|
this.currentCall.isMute = this.isMute;
|
|
2568
|
-
// } else {
|
|
2569
|
-
// }
|
|
2570
2432
|
}
|
|
2571
2433
|
async toggleMic() {
|
|
2572
2434
|
if (!this.audioStream) {
|
|
@@ -2578,6 +2440,12 @@ class CallProgressComponent {
|
|
|
2578
2440
|
track.enabled = this.micOn; // false = muted, true = sending audio
|
|
2579
2441
|
});
|
|
2580
2442
|
}
|
|
2443
|
+
getCurrentCallInfo() {
|
|
2444
|
+
return this.newIncomingCallsList
|
|
2445
|
+
.flatMap((callInfo) => callInfo.participants)
|
|
2446
|
+
.find((participant) => ((this.deviceNumberList.includes(participant?.from) && participant?.to === 'c2c_softphone_client')
|
|
2447
|
+
|| this.deviceNumberList.includes(participant?.to)) && !participant?.isLeft && !participant?.isHold);
|
|
2448
|
+
}
|
|
2581
2449
|
toggleKeypad() {
|
|
2582
2450
|
this.showKeypad = !this.showKeypad;
|
|
2583
2451
|
this.callInput = '';
|
|
@@ -2587,7 +2455,6 @@ class CallProgressComponent {
|
|
|
2587
2455
|
this.showContactsPanel = false;
|
|
2588
2456
|
return false;
|
|
2589
2457
|
}
|
|
2590
|
-
// this.isAddRemoveParticipant = false;
|
|
2591
2458
|
this.showContactsPanel = !isClose;
|
|
2592
2459
|
this.getAllParticipants(callInfo?.conferenceSid);
|
|
2593
2460
|
this.filteredList = this.contacts;
|
|
@@ -2597,29 +2464,15 @@ class CallProgressComponent {
|
|
|
2597
2464
|
this.applyFilter();
|
|
2598
2465
|
}
|
|
2599
2466
|
async addRemoveParticipant() {
|
|
2600
|
-
// const conferenceSId = this.addRes?.conferenceSid;
|
|
2601
2467
|
this.isAddRemoveParticipant = !this.isAddRemoveParticipant;
|
|
2602
2468
|
await this.getAllParticipants(this.currentCall.conferenceSid);
|
|
2603
2469
|
this.filteredParticipentList = this.allParticipentList;
|
|
2604
2470
|
}
|
|
2605
2471
|
async add(data) {
|
|
2606
|
-
// if(data?.status != 'ringing'){
|
|
2607
2472
|
this.isIncomingCallBtnDisable = true;
|
|
2608
2473
|
this.conferenceId = this.twilioService.conferenceCallInfo.conferenceId;
|
|
2609
2474
|
if (this.currentCallList.length > 1 && this.currentCall?.isAcceptCall) {
|
|
2610
2475
|
if (this.currentCall?.isConference) {
|
|
2611
|
-
// this.isConferenceCallHold = true;
|
|
2612
|
-
// this.currentCallList.forEach((res) => {
|
|
2613
|
-
// if (res.isConference) {
|
|
2614
|
-
// this.onholdOrUnholdParticipant({
|
|
2615
|
-
// participantId: [res.participantId],
|
|
2616
|
-
// conferenceId: res?.conferenceId,
|
|
2617
|
-
// hold: true,
|
|
2618
|
-
// mute: res?.mute || false,
|
|
2619
|
-
// conference: res.isConference || false
|
|
2620
|
-
// });
|
|
2621
|
-
// }
|
|
2622
|
-
// })
|
|
2623
2476
|
this.onholdOrUnholdParticipant({
|
|
2624
2477
|
participantId: [this.hostnumber.participantId],
|
|
2625
2478
|
conferenceId: this.hostnumber?.conferenceId,
|
|
@@ -2630,10 +2483,6 @@ class CallProgressComponent {
|
|
|
2630
2483
|
}
|
|
2631
2484
|
else {
|
|
2632
2485
|
this.isConferenceCallHold = false;
|
|
2633
|
-
// const index = this.currentCallList.findIndex((item: any) => item.participantId == this.currentCall?.participantId);
|
|
2634
|
-
// if (index != -1) {
|
|
2635
|
-
// // this.currentCallList[index].isHold = true;
|
|
2636
|
-
// }
|
|
2637
2486
|
await this.onholdOrUnholdParticipant({
|
|
2638
2487
|
participantId: this.currentCall?.isIncomingCall ? [this.currentCall?.id] : [this.currentCall?.participantId],
|
|
2639
2488
|
conferenceId: this.currentCall?.conferenceId,
|
|
@@ -2641,22 +2490,8 @@ class CallProgressComponent {
|
|
|
2641
2490
|
mute: this.currentCall?.mute || false,
|
|
2642
2491
|
conference: this.currentCall?.isConference || false
|
|
2643
2492
|
});
|
|
2644
|
-
// data.isHold = false;
|
|
2645
2493
|
}
|
|
2646
2494
|
}
|
|
2647
|
-
// let incomingCallData = this.currentCallList.filter((item: any) => item.isIncomingCall && item.isAcceptCall);
|
|
2648
|
-
// if (this.currentCallList.length > 1) {
|
|
2649
|
-
// // this.call = await this.twilioService.connect('');
|
|
2650
|
-
// this.twilioService.addIncomingParticipant(data?.id, this.twilioService.conferenceCallInfo.conferenceId).subscribe((res: any) => {
|
|
2651
|
-
// console.log(res, 'bhhhhhhhhhhhhhhhhhhh')
|
|
2652
|
-
// this.incomeingCallSocketService.isCurrentIncomingCallList.push(data?.id || data?.participantId);
|
|
2653
|
-
// this.incomeingCallSocketService.pause();
|
|
2654
|
-
// data.isAcceptCall = true;
|
|
2655
|
-
// // this.currentCall = data;
|
|
2656
|
-
// this.setIncomingCallStatus(data)
|
|
2657
|
-
// })
|
|
2658
|
-
// } else {
|
|
2659
|
-
// this.currentCall = data;
|
|
2660
2495
|
let payload = {
|
|
2661
2496
|
recordId: data?.id,
|
|
2662
2497
|
ipAddress: '',
|
|
@@ -2718,7 +2553,6 @@ class CallProgressComponent {
|
|
|
2718
2553
|
conference: true
|
|
2719
2554
|
});
|
|
2720
2555
|
this.callData = {
|
|
2721
|
-
// ...this.callData,
|
|
2722
2556
|
phone: phoneNumber,
|
|
2723
2557
|
displayNum: phoneNumber,
|
|
2724
2558
|
name: contact?.name || `${contact?.firstName} ${contact?.lastName}` || phoneNumber,
|
|
@@ -2746,24 +2580,12 @@ class CallProgressComponent {
|
|
|
2746
2580
|
conference: true
|
|
2747
2581
|
});
|
|
2748
2582
|
}
|
|
2749
|
-
else {
|
|
2750
|
-
await this.onholdOrUnholdParticipant({
|
|
2751
|
-
participantId: [c?.participantId],
|
|
2752
|
-
conferenceId: c.conferenceId,
|
|
2753
|
-
hold: true,
|
|
2754
|
-
mute: c?.mute || false,
|
|
2755
|
-
conference: c?.isConference || false
|
|
2756
|
-
});
|
|
2757
|
-
}
|
|
2758
2583
|
});
|
|
2759
2584
|
// Put current call on hold
|
|
2760
2585
|
this.isCallOnHold = true;
|
|
2761
2586
|
this.showContactsPanel = false;
|
|
2762
2587
|
this.showRingAnimation = true;
|
|
2763
2588
|
this.isConference = true;
|
|
2764
|
-
// const contactName = [contact?.firstName, contact?.middleName, contact?.lastName]
|
|
2765
|
-
// .filter(Boolean)
|
|
2766
|
-
// .join(' ');
|
|
2767
2589
|
// Add participant to the conference
|
|
2768
2590
|
let data = await this.addParticipantToCall({
|
|
2769
2591
|
from: this.callData?.from || this.selectedCallerId?.number,
|
|
@@ -2795,9 +2617,6 @@ class CallProgressComponent {
|
|
|
2795
2617
|
isConference: false
|
|
2796
2618
|
};
|
|
2797
2619
|
this.cdr.detectChanges();
|
|
2798
|
-
console.log(this.callData, 'this.callData');
|
|
2799
|
-
console.log('test111111');
|
|
2800
|
-
console.log("Participant added to conference:", phoneNumber);
|
|
2801
2620
|
this.showRingAnimation = false;
|
|
2802
2621
|
}
|
|
2803
2622
|
}
|
|
@@ -2813,13 +2632,6 @@ class CallProgressComponent {
|
|
|
2813
2632
|
if (isInvalid) {
|
|
2814
2633
|
return false;
|
|
2815
2634
|
}
|
|
2816
|
-
// this.isSavedContactDialled();
|
|
2817
|
-
// this.isPaymentDue = localStorage.getItem('paymentDue') === 'false' ? false : true;
|
|
2818
|
-
// if (this.isPaymentDue) {
|
|
2819
|
-
// swal('Warning', 'Please note that your payment is due, To continue on your services kindly subscribe to use uninterrupted services.');
|
|
2820
|
-
// return false;
|
|
2821
|
-
// }
|
|
2822
|
-
// this.isTrialPeriodOver = localStorage.getItem('trialOver') === 'false' ? false : true;
|
|
2823
2635
|
let alreadyInCall = this.currentCallList.find((res) => res.to == number || res.from == number);
|
|
2824
2636
|
if (alreadyInCall) {
|
|
2825
2637
|
swal('Error', `Already ${number} number in this call.`);
|
|
@@ -2829,32 +2641,10 @@ class CallProgressComponent {
|
|
|
2829
2641
|
swal('Error', 'You can not dial this number');
|
|
2830
2642
|
return false;
|
|
2831
2643
|
}
|
|
2832
|
-
// const hasPermission = await this.checkMicrophonePermission();
|
|
2833
|
-
// if (!hasPermission) {
|
|
2834
|
-
// await this.askForMicrophonePermission();
|
|
2835
|
-
// return false;
|
|
2836
|
-
// }
|
|
2837
|
-
// this.isLoadershow = true;
|
|
2838
|
-
// if (!this.selectedCallerId) {
|
|
2839
|
-
// this.shakeDedicatedBtn = true;
|
|
2840
|
-
// this.showDialAlert('Select a C2C number to call');
|
|
2841
|
-
// setTimeout(() => {
|
|
2842
|
-
// this.shakeDedicatedBtn = false;
|
|
2843
|
-
// }, 3000);
|
|
2844
|
-
// this.isLoadershow = false;
|
|
2845
|
-
// return false;
|
|
2846
|
-
// }
|
|
2847
|
-
// Clear displayNum if value is bound from previous call
|
|
2848
|
-
// this.callData.displayNum = '';
|
|
2849
|
-
// Get number to be dialed from backend
|
|
2850
2644
|
let contact = this.contacts.find((contact) => {
|
|
2851
2645
|
return contact.numbersList.some((num) => num.number === number);
|
|
2852
2646
|
});
|
|
2853
2647
|
number = await this.getToNumber(number);
|
|
2854
|
-
// if (this.terminateCall) {
|
|
2855
|
-
// this.terminateCall = false;
|
|
2856
|
-
// return;
|
|
2857
|
-
// }
|
|
2858
2648
|
// Update call data in a single operation
|
|
2859
2649
|
const callData = {
|
|
2860
2650
|
name: contact?.firstName,
|
|
@@ -2866,50 +2656,39 @@ class CallProgressComponent {
|
|
|
2866
2656
|
from: this.selectedCallerId.number,
|
|
2867
2657
|
timestamp: new Date().toISOString()
|
|
2868
2658
|
};
|
|
2869
|
-
// console.log('dd10')
|
|
2870
|
-
// this.isCallInProgress = true;
|
|
2871
2659
|
console.log('call startted', callData);
|
|
2872
2660
|
if (isNewConference) {
|
|
2873
|
-
// if(this.currentCall.isConference) {
|
|
2874
2661
|
this.isNewAddedCall = true;
|
|
2875
|
-
let
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2662
|
+
let ourNumberInfo = {};
|
|
2663
|
+
let callInfo = this.newIncomingCallsList.find((callInfo, i) => this.currentCall.conferenceId == callInfo.conferenceId);
|
|
2664
|
+
if (callInfo) {
|
|
2665
|
+
ourNumberInfo = callInfo.participants.find((resData) => ((this.deviceNumberList.includes(resData?.from) && resData?.to == 'c2c_softphone_client') || (this.deviceNumberList.includes(resData?.to))) && !resData?.isLeft);
|
|
2666
|
+
}
|
|
2667
|
+
if (ourNumberInfo?.id) {
|
|
2668
|
+
console.log(ourNumberInfo, 'selfInfo');
|
|
2882
2669
|
await this.onholdOrUnholdParticipant({
|
|
2883
|
-
participantId:
|
|
2884
|
-
conferenceId:
|
|
2670
|
+
participantId: [ourNumberInfo?.id],
|
|
2671
|
+
conferenceId: ourNumberInfo?.conferenceId,
|
|
2885
2672
|
hold: true,
|
|
2886
|
-
mute:
|
|
2887
|
-
conference:
|
|
2673
|
+
mute: ourNumberInfo?.mute || false,
|
|
2674
|
+
conference: ourNumberInfo?.isConference || false
|
|
2888
2675
|
});
|
|
2889
|
-
|
|
2890
|
-
this.isConferenceCallHold = true;
|
|
2891
|
-
}
|
|
2676
|
+
this.isConferenceCallHold = true;
|
|
2892
2677
|
this.startCall(callData, isNewConference);
|
|
2893
2678
|
}
|
|
2894
2679
|
else {
|
|
2895
2680
|
this.startCall(callData, isNewConference);
|
|
2896
2681
|
}
|
|
2897
2682
|
this.searchText = '';
|
|
2898
|
-
// }
|
|
2899
2683
|
}
|
|
2900
2684
|
else {
|
|
2901
2685
|
this.searchText = '';
|
|
2902
2686
|
this.callContact(number, true);
|
|
2903
2687
|
}
|
|
2904
|
-
// this.callInitiated.emit({ ...this.callData });
|
|
2905
2688
|
return true;
|
|
2906
2689
|
}
|
|
2907
2690
|
catch (e) {
|
|
2908
|
-
// console.error('Error in initiateCall:', e);
|
|
2909
|
-
// this.isLoadershow = false;
|
|
2910
2691
|
this.showDialAlert('Failed to initiate call. Please try again.');
|
|
2911
|
-
// console.log('dd11')
|
|
2912
|
-
// this.isCallInProgress = false;
|
|
2913
2692
|
return false;
|
|
2914
2693
|
}
|
|
2915
2694
|
}
|
|
@@ -2959,193 +2738,131 @@ class CallProgressComponent {
|
|
|
2959
2738
|
}
|
|
2960
2739
|
getAllParticipants(conferenceSid) {
|
|
2961
2740
|
this.extensionService.getAllParticipants(conferenceSid).subscribe((res) => {
|
|
2962
|
-
this.allParticipentList = res.participants.filter((resInfo) => resInfo?.to
|
|
2741
|
+
this.allParticipentList = res.participants.filter((resInfo) => !(resInfo?.to == 'c2c_softphone_client' && resInfo?.direction == 'incoming-call'));
|
|
2963
2742
|
;
|
|
2964
2743
|
this.filteredParticipentList = this.allParticipentList;
|
|
2965
2744
|
this.applyFilter();
|
|
2966
|
-
// let index = this.contacts.findIndex((c:any)=> c?.numbersList[0]?.number == res?.to);
|
|
2967
|
-
// if(index > -1){
|
|
2968
|
-
// this.contacts[index].isCallOnHold = true;
|
|
2969
|
-
// }
|
|
2970
|
-
// else {
|
|
2971
|
-
// res['IsConnected'] = true;
|
|
2972
|
-
// this.contacts.push(res)
|
|
2973
|
-
// }
|
|
2974
2745
|
});
|
|
2975
2746
|
}
|
|
2976
|
-
// acceptConcurrentCall(incomingCall: any) {
|
|
2977
|
-
// if (!incomingCall) return;
|
|
2978
|
-
// // Put current call on hold instead of disconnecting
|
|
2979
|
-
// if (this.call) {
|
|
2980
|
-
// this.heldCall = this.call;
|
|
2981
|
-
// this.isCallOnHold = true;
|
|
2982
|
-
// // Mute the held call
|
|
2983
|
-
// this.heldCall.mute(true);
|
|
2984
|
-
// }
|
|
2985
|
-
// incomingCall.accept();
|
|
2986
|
-
// this.call = incomingCall;
|
|
2987
|
-
// this.callData.phone = incomingCall.parameters['From'];
|
|
2988
|
-
// this.callData.name = incomingCall.customParameters?.get('name') || '-';
|
|
2989
|
-
// this.callData.img = incomingCall.customParameters?.get('image') || 'assets/images/user.jpg';
|
|
2990
|
-
// this.isConcurrentIncoming = false;
|
|
2991
|
-
// this.incomingCallDiv = false;
|
|
2992
|
-
// this.disbaleEndCallBtn = false;
|
|
2993
|
-
// // Reset timer for new call
|
|
2994
|
-
// this.stopTimer();
|
|
2995
|
-
// this.startTimer();
|
|
2996
|
-
// this.cdr.detectChanges();
|
|
2997
|
-
// }
|
|
2998
|
-
acceptConcurrentCall(incomingCall) {
|
|
2999
|
-
if (!incomingCall)
|
|
3000
|
-
return;
|
|
3001
|
-
// Put current call on hold instead of disconnecting
|
|
3002
|
-
// if (this.call) {
|
|
3003
|
-
// // this.heldCall = this.call;
|
|
3004
|
-
// this.isCallOnHold = true;
|
|
3005
|
-
// // // Mute the held call
|
|
3006
|
-
// // this.heldCall.mute(true);
|
|
3007
|
-
// // }
|
|
3008
|
-
// // Accept the new call
|
|
3009
|
-
// incomingCall.accept();
|
|
3010
|
-
// this.call = incomingCall;
|
|
3011
|
-
// this.callData.phone = incomingCall.parameters['From'];
|
|
3012
|
-
// this.callData.name = incomingCall.customParameters?.get('name') || '-';
|
|
3013
|
-
// this.callData.img = incomingCall.customParameters?.get('image') || 'assets/images/user.jpg';
|
|
3014
|
-
// this.isConcurrentIncoming = false;
|
|
3015
|
-
// this.incomingCallDiv = false;
|
|
3016
|
-
// this.disbaleEndCallBtn = false;
|
|
3017
|
-
// // 🟢 Remove the accepted call from incoming list
|
|
3018
|
-
// this.newIncomingCallsList = (this.newIncomingCallsList || []).filter(
|
|
3019
|
-
// (c: any) => c?.parameters?.CallSid !== incomingCall?.parameters?.CallSid
|
|
3020
|
-
// );
|
|
3021
|
-
// this.incomingCallsNewInfo.emit(this.newIncomingCallsList);
|
|
3022
|
-
// // 🕒 Reset timer for new call
|
|
3023
|
-
// this.stopTimer();
|
|
3024
|
-
// this.startTimer();
|
|
3025
|
-
// this.cdr.detectChanges();
|
|
3026
|
-
}
|
|
3027
2747
|
async swapCalls(callInfo, isConferenceCall) {
|
|
3028
2748
|
// if (!this.heldCall || !this.call) return;
|
|
3029
2749
|
console.log(this.call, 'this.call');
|
|
3030
2750
|
console.log(this.heldCall, 'this.heldCall');
|
|
3031
2751
|
console.log(this.currentCallList, 'this.currentCallList');
|
|
3032
2752
|
console.log(callInfo, 'callInfo for swapCalls');
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
participantId: [c?.participantId],
|
|
3038
|
-
conferenceId: c.conferenceId,
|
|
3039
|
-
hold: true,
|
|
3040
|
-
mute: c?.mute || false,
|
|
3041
|
-
conference: c?.isConference || false
|
|
3042
|
-
});
|
|
3043
|
-
// this.isConferenceCallHold = true;
|
|
3044
|
-
}
|
|
3045
|
-
else if (isConferenceCall && c?.conferenceId == callInfo.conferenceId && c.isConference) {
|
|
3046
|
-
await this.onholdOrUnholdParticipant({
|
|
3047
|
-
participantId: [c?.participantId],
|
|
3048
|
-
conferenceId: c.conferenceId,
|
|
3049
|
-
hold: false,
|
|
3050
|
-
mute: c?.mute || false,
|
|
3051
|
-
conference: true
|
|
3052
|
-
});
|
|
3053
|
-
this.isConference = true;
|
|
3054
|
-
this.isConferenceCallHold = false;
|
|
3055
|
-
}
|
|
3056
|
-
else if (callInfo?.isHold && c?.participantId === callInfo?.participantId) {
|
|
3057
|
-
await this.onholdOrUnholdParticipant({
|
|
3058
|
-
participantId: [c?.participantId],
|
|
3059
|
-
conferenceId: c.conferenceId,
|
|
3060
|
-
hold: false,
|
|
3061
|
-
mute: c?.mute || false,
|
|
3062
|
-
conference: c?.isConference || false
|
|
3063
|
-
});
|
|
3064
|
-
}
|
|
3065
|
-
});
|
|
3066
|
-
}
|
|
3067
|
-
else if (isConferenceCall) {
|
|
3068
|
-
this.currentCallList.forEach(async (c) => {
|
|
3069
|
-
if (c?.isConference && callInfo?.conferenceId == c?.conferenceId) {
|
|
2753
|
+
this.newIncomingCallsList.forEach(async (c) => {
|
|
2754
|
+
if (c?.conferenceId == callInfo?.conferenceId) {
|
|
2755
|
+
let participantInfo = c.participants.find((resData) => ((this.deviceNumberList.includes(resData?.from) && resData?.to == 'c2c_softphone_client') || (this.deviceNumberList.includes(resData?.to))) && !resData?.isLeft);
|
|
2756
|
+
if (participantInfo?.id) {
|
|
3070
2757
|
await this.onholdOrUnholdParticipant({
|
|
3071
|
-
participantId: [
|
|
3072
|
-
conferenceId:
|
|
2758
|
+
participantId: [participantInfo?.id],
|
|
2759
|
+
conferenceId: participantInfo?.conferenceId,
|
|
3073
2760
|
hold: false,
|
|
3074
|
-
mute:
|
|
3075
|
-
conference:
|
|
3076
|
-
});
|
|
3077
|
-
}
|
|
3078
|
-
else {
|
|
3079
|
-
// c.isHold = true;
|
|
3080
|
-
await this.onholdOrUnholdParticipant({
|
|
3081
|
-
participantId: [c?.participantId],
|
|
3082
|
-
conferenceId: c.conferenceId,
|
|
3083
|
-
hold: true,
|
|
3084
|
-
mute: c?.mute || false,
|
|
3085
|
-
conference: c?.isConference || false
|
|
2761
|
+
mute: participantInfo?.mute || false,
|
|
2762
|
+
conference: participantInfo?.isConference || false
|
|
3086
2763
|
});
|
|
2764
|
+
// this.isConferenceCallHold = true;
|
|
3087
2765
|
}
|
|
3088
|
-
}
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
this.currentCallList.forEach(async (c) => {
|
|
3093
|
-
if (c?.participantId && !c?.isHold) {
|
|
2766
|
+
}
|
|
2767
|
+
else {
|
|
2768
|
+
let participantInfo = c.participants.find((resData) => ((this.deviceNumberList.includes(resData?.from) && resData?.to == 'c2c_softphone_client') || (this.deviceNumberList.includes(resData?.to))) && !resData?.isLeft);
|
|
2769
|
+
if (participantInfo?.id && !participantInfo?.isHold) {
|
|
3094
2770
|
await this.onholdOrUnholdParticipant({
|
|
3095
|
-
participantId: [
|
|
3096
|
-
conferenceId:
|
|
2771
|
+
participantId: [participantInfo?.id],
|
|
2772
|
+
conferenceId: participantInfo?.conferenceId,
|
|
3097
2773
|
hold: true,
|
|
3098
|
-
mute:
|
|
3099
|
-
conference:
|
|
3100
|
-
});
|
|
3101
|
-
}
|
|
3102
|
-
else if (callInfo?.isHold && c?.participantId === callInfo?.participantId) {
|
|
3103
|
-
await this.onholdOrUnholdParticipant({
|
|
3104
|
-
participantId: [c?.participantId],
|
|
3105
|
-
conferenceId: c.conferenceId,
|
|
3106
|
-
hold: false,
|
|
3107
|
-
mute: c?.mute || false,
|
|
3108
|
-
conference: c?.isConference || false
|
|
2774
|
+
mute: participantInfo?.mute || false,
|
|
2775
|
+
conference: participantInfo?.isConference || false
|
|
3109
2776
|
});
|
|
2777
|
+
// this.isConferenceCallHold = true;
|
|
3110
2778
|
}
|
|
3111
|
-
}
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
//
|
|
3125
|
-
//
|
|
3126
|
-
//
|
|
3127
|
-
//
|
|
3128
|
-
//
|
|
3129
|
-
//
|
|
3130
|
-
//
|
|
3131
|
-
//
|
|
3132
|
-
//
|
|
3133
|
-
//
|
|
3134
|
-
//
|
|
3135
|
-
//
|
|
3136
|
-
//
|
|
3137
|
-
//
|
|
3138
|
-
//
|
|
3139
|
-
//
|
|
3140
|
-
//
|
|
3141
|
-
//
|
|
3142
|
-
//
|
|
3143
|
-
//
|
|
3144
|
-
//
|
|
3145
|
-
//
|
|
3146
|
-
//
|
|
3147
|
-
//
|
|
3148
|
-
|
|
2779
|
+
}
|
|
2780
|
+
if (c?.isConference && !c?.isHold && this.currentCall?.conferenceId == c?.conferenceId) {
|
|
2781
|
+
await this.onholdOrUnholdParticipant({
|
|
2782
|
+
participantId: [c?.participantId],
|
|
2783
|
+
conferenceId: c.conferenceId,
|
|
2784
|
+
hold: true,
|
|
2785
|
+
mute: c?.mute || false,
|
|
2786
|
+
conference: c?.isConference || false
|
|
2787
|
+
});
|
|
2788
|
+
// this.isConferenceCallHold = true;
|
|
2789
|
+
}
|
|
2790
|
+
});
|
|
2791
|
+
// if (this.currentCall?.isConference) {
|
|
2792
|
+
// this.currentCallList.forEach(async (c: any) => {
|
|
2793
|
+
// if (c?.isConference && !c?.isHold && this.currentCall?.conferenceId == c?.conferenceId) {
|
|
2794
|
+
// await this.onholdOrUnholdParticipant({
|
|
2795
|
+
// participantId: [c?.participantId],
|
|
2796
|
+
// conferenceId: c.conferenceId,
|
|
2797
|
+
// hold: true,
|
|
2798
|
+
// mute: c?.mute || false,
|
|
2799
|
+
// conference: c?.isConference || false
|
|
2800
|
+
// });
|
|
2801
|
+
// // this.isConferenceCallHold = true;
|
|
2802
|
+
// } else if (isConferenceCall && c?.conferenceId == callInfo.conferenceId && c.isConference) {
|
|
2803
|
+
// await this.onholdOrUnholdParticipant({
|
|
2804
|
+
// participantId: [c?.participantId],
|
|
2805
|
+
// conferenceId: c.conferenceId,
|
|
2806
|
+
// hold: false,
|
|
2807
|
+
// mute: c?.mute || false,
|
|
2808
|
+
// conference: true
|
|
2809
|
+
// });
|
|
2810
|
+
// this.isConference = true;
|
|
2811
|
+
// this.isConferenceCallHold = false
|
|
2812
|
+
// } else if (callInfo?.isHold && c?.participantId === callInfo?.participantId) {
|
|
2813
|
+
// await this.onholdOrUnholdParticipant({
|
|
2814
|
+
// participantId: [c?.participantId],
|
|
2815
|
+
// conferenceId: c.conferenceId,
|
|
2816
|
+
// hold: false,
|
|
2817
|
+
// mute: c?.mute || false,
|
|
2818
|
+
// conference: c?.isConference || false
|
|
2819
|
+
// });
|
|
2820
|
+
// }
|
|
2821
|
+
// });
|
|
2822
|
+
// } else if (isConferenceCall) {
|
|
2823
|
+
// this.currentCallList.forEach(async (c: any) => {
|
|
2824
|
+
// if (c?.isConference && callInfo?.conferenceId == c?.conferenceId) {
|
|
2825
|
+
// await this.onholdOrUnholdParticipant({
|
|
2826
|
+
// participantId: [c?.participantId],
|
|
2827
|
+
// conferenceId: c.conferenceId,
|
|
2828
|
+
// hold: false,
|
|
2829
|
+
// mute: c?.mute || false,
|
|
2830
|
+
// conference: c?.isConference || false
|
|
2831
|
+
// });
|
|
2832
|
+
// } else {
|
|
2833
|
+
// // c.isHold = true;
|
|
2834
|
+
// await this.onholdOrUnholdParticipant({
|
|
2835
|
+
// participantId: [c?.participantId],
|
|
2836
|
+
// conferenceId: c.conferenceId,
|
|
2837
|
+
// hold: true,
|
|
2838
|
+
// mute: c?.mute || false,
|
|
2839
|
+
// conference: c?.isConference || false
|
|
2840
|
+
// });
|
|
2841
|
+
// }
|
|
2842
|
+
// });
|
|
2843
|
+
// } else {
|
|
2844
|
+
// this.isConferenceCallHold = false;
|
|
2845
|
+
// this.currentCallList.forEach(async (c: any) => {
|
|
2846
|
+
// if (c?.participantId && !c?.isHold) {
|
|
2847
|
+
// await this.onholdOrUnholdParticipant({
|
|
2848
|
+
// participantId: [c?.participantId],
|
|
2849
|
+
// conferenceId: c.conferenceId,
|
|
2850
|
+
// hold: true,
|
|
2851
|
+
// mute: c?.mute || false,
|
|
2852
|
+
// conference: c?.isConference || false
|
|
2853
|
+
// });
|
|
2854
|
+
// } else if (callInfo?.isHold && c?.participantId === callInfo?.participantId) {
|
|
2855
|
+
// await this.onholdOrUnholdParticipant({
|
|
2856
|
+
// participantId: [c?.participantId],
|
|
2857
|
+
// conferenceId: c.conferenceId,
|
|
2858
|
+
// hold: false,
|
|
2859
|
+
// mute: c?.mute || false,
|
|
2860
|
+
// conference: c?.isConference || false
|
|
2861
|
+
// });
|
|
2862
|
+
// }
|
|
2863
|
+
// });
|
|
2864
|
+
// }
|
|
2865
|
+
// console.log('this.currentCallList after swap', this.currentCallList);
|
|
3149
2866
|
this.cdr.detectChanges();
|
|
3150
2867
|
}
|
|
3151
2868
|
isMergeCallAllowed() {
|
|
@@ -3158,45 +2875,23 @@ class CallProgressComponent {
|
|
|
3158
2875
|
this.currentCallList.forEach(async (c) => {
|
|
3159
2876
|
if (c.conferenceId == this.currentCall.conferenceId) {
|
|
3160
2877
|
if (c?.participantId) {
|
|
3161
|
-
//
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
});
|
|
2878
|
+
// await this.onholdOrUnholdParticipant({
|
|
2879
|
+
// participantId: [c?.participantId],
|
|
2880
|
+
// conferenceId: c.conferenceId,
|
|
2881
|
+
// hold: false,
|
|
2882
|
+
// mute: c?.mute || false,
|
|
2883
|
+
// conference: true
|
|
2884
|
+
// });
|
|
3169
2885
|
c.isConference = true;
|
|
3170
|
-
// } else if(c?.participantId && c.isIncomingCall){
|
|
3171
|
-
// await this.twilioService.addIncomingParticipant(c?.participantId, this.conferenceId).subscribe((data: any) => {
|
|
3172
|
-
// console.log(data,'bhhhhhhhhhhhhhhhhhhh')
|
|
3173
|
-
// })
|
|
3174
|
-
// c.isHold = false;
|
|
3175
|
-
// c.isConference = true;
|
|
3176
2886
|
}
|
|
3177
2887
|
this.isConferenceCallHold = false;
|
|
3178
2888
|
}
|
|
3179
2889
|
});
|
|
3180
|
-
// await this.onholdOrUnholdParticipant({
|
|
3181
|
-
// participantId: this.heldCall?.callInfo?.participantId,
|
|
3182
|
-
// conferenceId: this.conferenceId,
|
|
3183
|
-
// hold: false
|
|
3184
|
-
// });
|
|
3185
|
-
// this.heldCall.mute(false);
|
|
3186
|
-
// this.call.mute(false);
|
|
3187
2890
|
this.isCallOnHold = false;
|
|
3188
2891
|
this.isConference = true;
|
|
3189
2892
|
this.cdr.detectChanges();
|
|
3190
2893
|
}
|
|
3191
2894
|
}
|
|
3192
|
-
endHeldCall() {
|
|
3193
|
-
// if (this.heldCall) {
|
|
3194
|
-
// this.heldCall.disconnect();
|
|
3195
|
-
// this.heldCall = undefined;
|
|
3196
|
-
// this.isCallOnHold = false;
|
|
3197
|
-
// this.cdr.detectChanges();
|
|
3198
|
-
// }
|
|
3199
|
-
}
|
|
3200
2895
|
hasDetailedInfo(callData) {
|
|
3201
2896
|
if (!callData)
|
|
3202
2897
|
return false;
|
|
@@ -3215,57 +2910,6 @@ class CallProgressComponent {
|
|
|
3215
2910
|
}
|
|
3216
2911
|
return false;
|
|
3217
2912
|
}
|
|
3218
|
-
// onClickExpand(data?: any): void {
|
|
3219
|
-
// if (this.selectedIncomingCall === data && this.isClickExpand) {
|
|
3220
|
-
// this.isClickExpand = false;
|
|
3221
|
-
// this.selectedIncomingCall = null;
|
|
3222
|
-
// // this.selectedIncomingCallInfo.emit({});
|
|
3223
|
-
// return;
|
|
3224
|
-
// }
|
|
3225
|
-
// this.isClickExpand = true;
|
|
3226
|
-
// this.selectedIncomingCall = data;
|
|
3227
|
-
// if (this.selectedIncomingCall) {
|
|
3228
|
-
// this.selectedIncomingCall['isClickExpand'] = true;
|
|
3229
|
-
// if (this.newIncomingCallsList && this.newIncomingCallsList.length > 0) {
|
|
3230
|
-
// this.newIncomingCallsList.forEach((call: any) => {
|
|
3231
|
-
// if (call !== this.selectedIncomingCall) {
|
|
3232
|
-
// call['isClickExpand'] = false;
|
|
3233
|
-
// }
|
|
3234
|
-
// });
|
|
3235
|
-
// }
|
|
3236
|
-
// // this.selectedIncomingCallInfo.emit(this.selectedIncomingCall);
|
|
3237
|
-
// if (!this.selectedIncomingCall.userInfo || this.selectedIncomingCall.userInfo.status == 201) {
|
|
3238
|
-
// // this.getUserInformation(this.selectedIncomingCall);
|
|
3239
|
-
// }
|
|
3240
|
-
// }
|
|
3241
|
-
// }
|
|
3242
|
-
// getUserInformation(incomingCallData: any) {
|
|
3243
|
-
// let data = this.fromEntries(Array.from(incomingCallData.customParameters.entries()));
|
|
3244
|
-
// this.extensionService.getUserInformation(data['twilioAuthId']).subscribe(
|
|
3245
|
-
// response => {
|
|
3246
|
-
// setTimeout(()=>{
|
|
3247
|
-
// incomingCallData['userInfo']=response
|
|
3248
|
-
// }, 5000)
|
|
3249
|
-
// }, error => {
|
|
3250
|
-
// console.error('Error starting recording', error);
|
|
3251
|
-
// });
|
|
3252
|
-
// }
|
|
3253
|
-
// rejectConcurrentCall(incomingCall: any) {
|
|
3254
|
-
// if (!incomingCall) return;
|
|
3255
|
-
// if (incomingCall.reject) {
|
|
3256
|
-
// incomingCall.reject();
|
|
3257
|
-
// }
|
|
3258
|
-
// if (incomingCall.disconnect) incomingCall.disconnect();
|
|
3259
|
-
// // Remove from list
|
|
3260
|
-
// this.newIncomingCallsList = (this.newIncomingCallsList || []).filter((c: any) => c?.parameters?.CallSid !== incomingCall?.parameters?.CallSid);
|
|
3261
|
-
// this.incomingCallsNewInfo.emit(this.newIncomingCallsList);
|
|
3262
|
-
// // If no more incoming, hide banner
|
|
3263
|
-
// if (!this.newIncomingCallsList || this.newIncomingCallsList.length === 0) {
|
|
3264
|
-
// this.isConcurrentIncoming = false;
|
|
3265
|
-
// this.incomingCallDiv = false;
|
|
3266
|
-
// }
|
|
3267
|
-
// this.cdr.detectChanges();
|
|
3268
|
-
// }
|
|
3269
2913
|
onCallInputs(num) {
|
|
3270
2914
|
try {
|
|
3271
2915
|
if (Number.isInteger(num) || num == '+' || num == '*' || num == '#') {
|
|
@@ -3297,13 +2941,10 @@ class CallProgressComponent {
|
|
|
3297
2941
|
}
|
|
3298
2942
|
}
|
|
3299
2943
|
closeIncomingCall(data) {
|
|
3300
|
-
// this.incomingCallDiv = false;
|
|
3301
2944
|
if (data.show) {
|
|
3302
|
-
//this.showCallProgressEvent.emit()
|
|
3303
2945
|
// handle incoming call accepted
|
|
3304
2946
|
this.startTimer();
|
|
3305
2947
|
this.disbaleEndCallBtn = false;
|
|
3306
|
-
// this.call = data.call;
|
|
3307
2948
|
this.isConcurrentIncoming = false;
|
|
3308
2949
|
this.incomingCallDiv = false;
|
|
3309
2950
|
const incomingDetail = this.extensionService.getCallSid();
|
|
@@ -3352,9 +2993,6 @@ class CallProgressComponent {
|
|
|
3352
2993
|
this.incomingCallSid = details.callSid;
|
|
3353
2994
|
this.incomingRecordCall = details.recordCall;
|
|
3354
2995
|
sid = this.incomingCallSid ? this.incomingCallSid : this.callSid || this.addRes?.conferenceSid;
|
|
3355
|
-
// if (!this.incomingRecordCall && !this.recordCall) {
|
|
3356
|
-
// return;
|
|
3357
|
-
// }
|
|
3358
2996
|
let payload = {
|
|
3359
2997
|
"conferenceId": this.currentCall?.conferenceId,
|
|
3360
2998
|
};
|
|
@@ -3368,9 +3006,6 @@ class CallProgressComponent {
|
|
|
3368
3006
|
});
|
|
3369
3007
|
}
|
|
3370
3008
|
stopRecording() {
|
|
3371
|
-
// if (!this.incomingRecordCall && !this.recordCall) {
|
|
3372
|
-
// return;
|
|
3373
|
-
// }
|
|
3374
3009
|
this.isRecording = false;
|
|
3375
3010
|
this.isPaused = false;
|
|
3376
3011
|
if (this.timerSubscription) {
|
|
@@ -3463,19 +3098,10 @@ class CallProgressComponent {
|
|
|
3463
3098
|
getUserInformation(id) {
|
|
3464
3099
|
this.extensionService.getUserInformation(id).subscribe((response) => {
|
|
3465
3100
|
console.log(response, 'userInformation');
|
|
3466
|
-
// this.selectedUserInfo = response.c2cInformation;
|
|
3467
|
-
// if(this.isClickExpand){
|
|
3468
|
-
// this.checkTextHeight();
|
|
3469
|
-
// }
|
|
3470
3101
|
}, error => {
|
|
3471
3102
|
console.error('Error starting recording', error);
|
|
3472
3103
|
});
|
|
3473
3104
|
}
|
|
3474
|
-
// incomingCallsNewList(data: any) {
|
|
3475
|
-
// console.log(data, 'newIncomingCallsListOUR')
|
|
3476
|
-
// this.newIncomingCallsList = data;
|
|
3477
|
-
// this.incomingCallsNewInfo.emit(this.newIncomingCallsList);
|
|
3478
|
-
// }
|
|
3479
3105
|
selectedIncomingCallInfo(data) {
|
|
3480
3106
|
this.selectedIncomingCall = data;
|
|
3481
3107
|
}
|
|
@@ -3552,11 +3178,6 @@ class CallProgressComponent {
|
|
|
3552
3178
|
(c?.middleName || '').toLowerCase().includes(text) || (c?.fullName || '').toLowerCase().includes(text) ||
|
|
3553
3179
|
(c?.numbersList[0]?.number || '').toLowerCase().includes(text) || (c?.numbersList[1]?.number || '').toLowerCase().includes(text);
|
|
3554
3180
|
});
|
|
3555
|
-
// this.filteredParticipentList = this.allParticipentList.filter((c: any) => {
|
|
3556
|
-
// const name = (c.direction == 'outgoing-call' ? (c?.toName || '') : (c?.fromName || '')).toLowerCase();
|
|
3557
|
-
// const number = (c.direction == 'outgoing-call' ? ( c?.to || '') : (c?.from || '')).toLowerCase();
|
|
3558
|
-
// return name.includes(text) || number.includes(text);
|
|
3559
|
-
// });
|
|
3560
3181
|
this.filteredList.forEach((c) => {
|
|
3561
3182
|
let index = this.currentCallList.findIndex((cc) => cc?.phone == c?.numbersList[0]?.number || cc?.phone == c?.numbersList[1]?.number);
|
|
3562
3183
|
if (index > -1) {
|
|
@@ -3576,6 +3197,20 @@ class CallProgressComponent {
|
|
|
3576
3197
|
toggleText() {
|
|
3577
3198
|
this.isExpanded = !this.isExpanded;
|
|
3578
3199
|
}
|
|
3200
|
+
// Call this when call disconnects
|
|
3201
|
+
onCallDisconnected() {
|
|
3202
|
+
this.showDisconnectModal = true;
|
|
3203
|
+
}
|
|
3204
|
+
endConference() {
|
|
3205
|
+
console.log('Conference Ended');
|
|
3206
|
+
this.showDisconnectModal = false;
|
|
3207
|
+
this.endCall(true);
|
|
3208
|
+
}
|
|
3209
|
+
leaveConference() {
|
|
3210
|
+
console.log('Left Conference');
|
|
3211
|
+
this.showDisconnectModal = false;
|
|
3212
|
+
this.onEndCall(this.hostnumber);
|
|
3213
|
+
}
|
|
3579
3214
|
ngOnDestroy() {
|
|
3580
3215
|
this.callData.dial = false;
|
|
3581
3216
|
if (this.timerSubscription) {
|
|
@@ -3584,10 +3219,10 @@ class CallProgressComponent {
|
|
|
3584
3219
|
}
|
|
3585
3220
|
}
|
|
3586
3221
|
CallProgressComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CallProgressComponent, deps: [{ token: ExtensionService }, { token: i0.ChangeDetectorRef }, { token: TwilioService }, { token: IpAddressService }, { token: IncomeingCallSocketService }], target: i0.ɵɵFactoryTarget.Component });
|
|
3587
|
-
CallProgressComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: CallProgressComponent, selector: "lib-call-progress", inputs: { callData: "callData", selectedCallerId: "selectedCallerId", newIncomingCallData: "newIncomingCallData", newIncomingCallsList: "newIncomingCallsList", callerIdList: "callerIdList", deviceId: "deviceId", conferenceCallInfo: "conferenceCallInfo" }, outputs: { endCallEvent: "endCallEvent", incomingCallsNewInfo: "incomingCallsNewInfo", minimiseEvent: "minimiseEvent", incomingCallInitiated: "incomingCallInitiated", isLoadershow: "isLoadershow", endIncomingCallEvent: "endIncomingCallEvent" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"d-flex\">\r\n <div class=\"call-container\" *ngIf=\"!isMinimised && currentCallList?.length\"\r\n [ngClass]=\"{'collops': isCollops, 'incoming-call-container': isClickExpand, 'contacts-open': showContactsPanel }\">\r\n <!-- <ng-container *ngIf=\"!incomingCallDiv || isConcurrentIncoming || true\"> -->\r\n <!-- All type Call Hold list -->\r\n <div class=\"held-call-banner\"\r\n *ngIf=\"currentCallList.length > 1 && !!currentCall && ((isConferenceCallHold || isConference) || !isConference)\">\r\n <ng-container *ngFor=\"let conf of conferenceCallList\">\r\n <div class=\"held-call-content\" *ngIf=\"conf?.isHold\">\r\n <div class=\"held-info\">\r\n <span class=\"material-symbols-outlined hold-icon\">pause_circle</span>\r\n <div class=\"held-caller\">\r\n <span class=\"held-label\">Hold</span>\r\n <span class=\"held-name\">Conference Call</span>\r\n </div>\r\n </div>\r\n <div class=\"held-actions\">\r\n <button class=\"conference-hold-contact\" [ngClass]=\"{ 'on-hold': conf?.isHold }\" (click)=\"swapCalls(conf,true)\">\r\n <span class=\"material-symbols-outlined\" title=\"{{'Hold'}}\"> phone_paused </span>\r\n </button>\r\n <button class=\"conference-contact\" (click)=\"endCall(true)\">\r\n <span class=\"material-symbols-outlined\" title=\"Call End\"> call_end </span>\r\n </button>\r\n <div class=\"togglearrow-arrow me-2\" id=\"togglearrow\"\r\n (click)=\"toggleContactsPanel(conf)\">\r\n <i class=\"fa fa-angle-right\"></i>\r\n </div>\r\n </div>\r\n </div>\r\n </ng-container>\r\n <ng-container *ngFor=\"let heldCall of currentCallList\">\r\n <div class=\"held-call-content\" *ngIf=\"heldCall?.isHold && !heldCall?.isConference\">\r\n <div class=\"held-info\">\r\n <span class=\"material-symbols-outlined hold-icon\">pause_circle</span>\r\n <div class=\"held-caller\">\r\n <span class=\"held-label\">Hold</span>\r\n <span class=\"held-name\">{{heldCall?.name || 'Unknown number'}}</span>\r\n <span class=\"held-number\">{{heldCall?.phone || ''}}</span>\r\n </div>\r\n </div>\r\n <div class=\"held-actions\">\r\n <button class=\"conference-hold-contact\" [ngClass]=\"{ 'on-hold': heldCall?.isHold }\" (click)=\"swapCalls(heldCall)\">\r\n <span class=\"material-symbols-outlined\" title=\"{{heldCall?.isHold? 'Resume':'Hold'}}\"> phone_paused </span>\r\n </button>\r\n <button class=\"conference-contact\" (click)=\"onEndCall(heldCall)\">\r\n <span class=\"material-symbols-outlined\" title=\"Call End\"> call_end </span>\r\n </button>\r\n <div class=\"togglearrow-arrow me-2\" id=\"togglearrow\" *ngIf=\"heldCall?.isIncomingCall\"\r\n (click)=\"onClickExpand(heldCall)\" [ngClass]=\"{'disabled': !heldCall?.businessNumber}\">\r\n <i class=\"fa fa-angle-right\"></i>\r\n </div>\r\n <!-- <button class=\"held-btn swap-btn\" (click)=\"swapCalls(heldCall)\" title=\"Swap calls\">\r\n <span class=\"material-symbols-outlined swap-icon\">swap_vert</span>\r\n </button> -->\r\n </div>\r\n </div>\r\n <div class=\"held-call-content\" *ngIf=\"heldCall?.isIncomingCall && !heldCall?.isAcceptCall\">\r\n <div class=\"held-info\">\r\n <span class=\"material-symbols-outlined hold-icon\">phone_callback</span>\r\n <div class=\"held-caller\">\r\n <span class=\"held-label\">Incoming Call</span>\r\n <span class=\"held-name\">{{heldCall?.name || 'Unknown number'}}</span>\r\n <span class=\"held-number\">{{heldCall?.phone || ''}}</span>\r\n </div>\r\n </div>\r\n <div class=\"held-actions\">\r\n <button class=\"banner-btn receive-btn\" *ngIf=\"!heldCall?.isAcceptCall\">\r\n <span class=\"material-symbols-outlined\" (click)=\"add(heldCall)\"> call </span>\r\n </button>\r\n <button class=\"call-btn-wrapper banner-btn reject-btn\">\r\n <span class=\"material-symbols-outlined\" (click)=\"onEndCall(heldCall)\"> call_end\r\n </span>\r\n </button>\r\n <div class=\"togglearrow-arrow me-2\" id=\"togglearrow\"\r\n (click)=\"onClickExpand(heldCall)\" [ngClass]=\"{'disabled': !heldCall?.businessNumber}\">\r\n <i class=\"fa fa-angle-right\"></i>\r\n </div>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n <!-- Compact banners for concurrent incoming (one per call) -->\r\n <!-- <ng-container *ngIf=\"currentCallList.length > 1 && !currentCall?.id\">\r\n <div class=\"incoming-banners-container\" *ngIf=\"!isConference && currentCallList.length > 1\">\r\n <div class=\"\">\r\n <ng-container *ngFor=\"let inc of currentCallList; let i = index\">\r\n <div class=\"incoming-banner\" *ngIf=\"inc?.isIncomingCall && !inc?.isAcceptCall\"\r\n [ngStyle]=\"{ top: ((isCallOnHold && heldCall) ? 64 : 0) + (i * 70) + 'px' }\">\r\n <div class=\"incoming-banner-content\">\r\n <div class=\"incoming-info\">\r\n <span class=\"incom ing-label\">Incoming call</span>\r\n <div class=\"incoming-caller\">\r\n <span class=\"caller-name\">{{ inc?.userInfo?.c2cInformation?.name ||\r\n inc?.customParameters?.get('name') || '-' }}</span>\r\n <span class=\"caller-number\">{{ inc?.userInfo?.c2cInformation?.number ||\r\n inc?.parameters?.From || '' }}</span>\r\n </div>\r\n </div>\r\n <div class=\"incoming-actions\">\r\n <button class=\"banner-btn accept-btn\" (click)=\"add(inc)\">\r\n <span class=\"material-symbols-outlined\">call</span>\r\n </button>\r\n <button class=\"banner-btn reject-btn\" (click)=\"onEndCall(inc)\">\r\n <span class=\"material-symbols-outlined\">call_end</span>\r\n </button>\r\n <div class=\"togglearrow-arrow me-2\" id=\"togglearrow\"\r\n (click)=\"onClickExpand(inc)\" [ngClass]=\"{'disabled': !inc?.businessNumber}\">\r\n <i class=\"fa fa-angle-right\"></i>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </ng-container> -->\r\n\r\n <!-- For single incoming call -->\r\n <div class=\"h-100 py-5\" style=\"display: flex; flex-direction: column;\"\r\n *ngIf=\"currentCallList.length === 1 && currentCallList[0]?.isIncomingCall && !currentCallList[0]?.isAcceptCall \">\r\n <div class=\"callToNum\">Incoming call on <br /><span>{{currentCallList[0]?.to || 'Unknown\r\n Number'}}</span>\r\n </div>\r\n <div class=\"call-animation\" [ngClass]=\"{'call-animation-play': showRingAnimation}\">\r\n <img class=\"avatar-img\" [src]=\"currentCallList[0]?.img\" alt=\"\" width=\"120\" />\r\n </div>\r\n <div class=\"callerDetails\">\r\n <h1>{{ currentCallList[0]?.name ? currentCallList[0]?.name : currentCallList[0]?.phone || 'Unknown Number' }}</h1>\r\n <p *ngIf=\"!!currentCallList[0]?.name\">{{ currentCallList[0]?.phone }}</p>\r\n </div>\r\n\r\n <div class=\"call-action-btns mt-auto\">\r\n <button class=\"call-btn receive-btn\" *ngIf=\"!newIncomingCallsList[0]?.isCallConnected\" [disabled]=\"isIncomingCallBtnDisable\">\r\n <span class=\"material-symbols-outlined\" (click)=\"add(currentCallList[0])\"> call </span>\r\n </button>\r\n <button class=\"call-btn reject-btn\">\r\n <span class=\"material-symbols-outlined\" (click)=\"onEndCall(currentCallList[0])\"> call_end\r\n </span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- For single active call --> \r\n <div *ngIf=\"(!isConference || isConferenceCallHold) && (!!currentCall?.id && !currentCall?.isConference)\"\r\n [ngStyle]=\"{'display': 'flex', 'flex-direction': 'column', 'position': 'relative'}\" class=\"active-call\">\r\n\r\n <div class=\"call-animation\" [ngClass]=\"{'call-animation-play': showRingAnimation}\">\r\n <img class=\"avatar-img\" [src]=\"currentCall?.img\" alt=\"\" width=\"120\" />\r\n </div>\r\n <div class=\"callerDetails\">\r\n <h1 [ngStyle]=\"{'margin-top': showKeypad ? '0': '8px'}\">{{currentCall?.name || 'Unknown number'}}\r\n </h1>\r\n <p>{{currentCall?.phone }}</p>\r\n <h4 style=\"margin-top: 4px\">{{currentCall?.time || timer}}</h4>\r\n </div>\r\n\r\n <div class=\"record-action-btns\" *ngIf=\"!showKeypad\"\r\n [ngStyle]=\"{'margin-top': showKeypad ? '0': '20px'}\">\r\n <div class=\"record-btn-container\">\r\n <button class=\"record-btn start-stop\" *ngIf=\"!isRecording\"\r\n [ngClass]=\"{'recording': isRecording, 'stopped': !isRecording}\" (click)=\"toggleRecording()\"\r\n [title]=\"isRecording ? 'Stop Recording' : 'Start Recording'\"\r\n [disabled]=\"!currentCall?.isAcceptCall\">\r\n <span class=\"recording-icon\"></span>\r\n </button>\r\n <div class=\"pause-resume-btns\">\r\n <button class=\"record-btn pause-resume\" *ngIf=\"isRecording && !isPaused\"\r\n (click)=\"pauseRecording()\">\r\n <span class=\"material-symbols-outlined\"> pause </span>\r\n </button>\r\n <button class=\"record-btn pause-resume\" *ngIf=\"isPaused\" (click)=\"resumeRecording()\">\r\n <span class=\"material-symbols-outlined\"> play_arrow </span>\r\n </button>\r\n </div>\r\n </div>\r\n <div *ngIf=\"isRecording\" class=\"timer-display\">\r\n {{ getFormattedTime() }}\r\n </div>\r\n </div>\r\n <div *ngIf=\"showKeypad\" class=\"sendDigit\">\r\n <input type=\"text\" name=\"call-inputs\" id=\"call-input\" [(ngModel)]=\"callInput\"\r\n (keyup)=\"onCallInputEnter($event)\">\r\n <span class=\"material-symbols-outlined input-clear-btn\" *ngIf=\"callInput\"\r\n (click)=\"clearInputs()\">close_small</span>\r\n </div>\r\n <div class=\"btn-container justify-content-center\" *ngIf=\"showKeypad\">\r\n <div class=\"key-btn\" *ngFor=\"let key of keypadVal\" (click)=\"onCallInputs(key.num)\">\r\n {{key.num}}\r\n <span class=\"btn-albhabets\">{{key.text ? key.text : ' '}}</span>\r\n </div>\r\n </div>\r\n\r\n <div class=\"call-action-btns\" [ngStyle]=\"{'margin-top': showKeypad ? '0': '723x'}\">\r\n <div class=\"mb-3\" *ngIf=\"!incomingCallDiv || isConcurrentIncoming\">\r\n <button class=\"held-btn merge-btn\" (click)=\"mergeCalls()\" title=\"Merge calls\"\r\n [disabled]=\"isMergeCallAllowed() || currentCallList.length < 2\">\r\n <span>Merge</span>\r\n </button>\r\n </div>\r\n <div class=\"flex align-items-center justify-content-evenly mb-3\">\r\n <button class=\"call-sec-btn mr-3\" [disabled]=\"!currentCall?.isAcceptCall\"\r\n (click)=\"toggleMute()\">\r\n <span class=\"material-symbols-outlined\" *ngIf=\"isMute\"> mic_off </span>\r\n <span class=\"material-symbols-outlined\" *ngIf=\"!isMute\"> mic </span>\r\n\r\n </button>\r\n <button class=\"call-sec-btn mr-3\" [disabled]=\"!currentCall?.isAcceptCall\">\r\n <span class=\"material-symbols-outlined\" (click)=\"toggleKeypad()\"> transition_dissolve\r\n </span>\r\n </button>\r\n <button class=\"call-sec-btn\" [disabled]=\"!currentCall?.isAcceptCall\"\r\n (click)=\"toggleContactsPanel(currentCall)\">\r\n <span class=\"material-symbols-outlined\"> groups_2 </span>\r\n </button>\r\n </div>\r\n\r\n <div>\r\n <button class=\"call-btn end-call-btn\" [disabled]=\"!currentCall?.isAcceptCall\"\r\n (click)=\"endCall()\">\r\n <span class=\"material-symbols-outlined\"> call_end </span>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- conference call view -->\r\n <div class=\"conference-call-view\" *ngIf=\"isConference && currentCall?.isConference\">\r\n <div class=\"conf-heading\">\r\n <span class=\"conf-icon material-symbols-outlined\"> groups </span>\r\n <span class=\"conf-title\">Conference Call</span>\r\n </div>\r\n\r\n <div class=\"scroll-container\">\r\n <div class=\"scroll-text conf-name\">\r\n <ng-container *ngFor=\"let call of currentCallList; let i = index\">\r\n <ng-container *ngIf=\"call?.isConference\">\r\n <span *ngIf=\"i != 0\">&</span>\r\n {{call?.name ? call?.name : call?.phone || 'Unknown number'}}\r\n </ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n <div class=\"conf-timer\">{{ timer }}</div>\r\n\r\n <div class=\"record-action-btns mt-auto\" *ngIf=\"!showKeypad\"\r\n [ngStyle]=\"{'margin-top': showKeypad ? '0': '20px'}\">\r\n <div class=\"record-btn-container\">\r\n <button class=\"record-btn start-stop\" *ngIf=\"!isRecording\"\r\n [ngClass]=\"{'recording': isRecording, 'stopped': !isRecording}\" (click)=\"toggleRecording()\"\r\n [title]=\"isRecording ? 'Stop Recording' : 'Start Recording'\">\r\n <span class=\"recording-icon\"></span>\r\n </button>\r\n <div class=\"pause-resume-btns\">\r\n <button class=\"record-btn pause-resume\" *ngIf=\"isRecording && !isPaused\"\r\n (click)=\"pauseRecording()\">\r\n <span class=\"material-symbols-outlined\"> pause </span>\r\n </button>\r\n <button class=\"record-btn pause-resume\" *ngIf=\"isPaused\" (click)=\"resumeRecording()\">\r\n <span class=\"material-symbols-outlined\"> play_arrow </span>\r\n </button>\r\n </div>\r\n </div>\r\n <div *ngIf=\"isRecording\" class=\"timer-display\">\r\n {{ getFormattedTime() }}\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"showKeypad\" class=\"sendDigit mt-2\">\r\n <input type=\"text\" name=\"call-inputs\" id=\"call-input\" [(ngModel)]=\"callInput\"\r\n (keyup)=\"onCallInputEnter($event)\">\r\n <span class=\"material-symbols-outlined input-clear-btn\" *ngIf=\"callInput\"\r\n (click)=\"clearInputs()\">close_small</span>\r\n </div>\r\n <div class=\"btn-container justify-content-center\" *ngIf=\"showKeypad\">\r\n <div class=\"key-btn\" *ngFor=\"let key of keypadVal\" (click)=\"onCallInputs(key.num)\">\r\n {{key.num}}\r\n <span class=\"btn-albhabets\">{{key.text ? key.text : ' '}}</span>\r\n </div>\r\n </div>\r\n\r\n <div class=\"conf-actions\">\r\n <button class=\"circle-btn\" [ngClass]=\"{'active': isMute}\" (click)=\"toggleMute(true)\">\r\n <span class=\"material-symbols-outlined\"> {{ isMute ? 'mic_off' : 'mic' }} </span>\r\n </button>\r\n <button class=\"circle-btn\" (click)=\"toggleKeypad()\">\r\n <span class=\"material-symbols-outlined\"> transition_dissolve </span>\r\n </button>\r\n <button class=\"circle-btn\" (click)=\"toggleContactsPanel(currentCall)\">\r\n <span class=\"material-symbols-outlined\"> groups_2 </span>\r\n </button>\r\n </div>\r\n\r\n <div class=\"conf-end\">\r\n <button class=\"circle-btn danger\" (click)=\"endCall(true)\">\r\n <span class=\"material-symbols-outlined\"> call_end </span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"wave-container\">\r\n <svg class=\"waves\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\r\n viewBox=\"0 24 150 28\" preserveAspectRatio=\"none\" shape-rendering=\"auto\">\r\n <defs>\r\n <path id=\"gentle-wave\"\r\n d=\"M-160 44c30 0 58-18 88-18s 58 18 88 18 58-18 88-18 58 18 88 18 v44h-352z\" />\r\n </defs>\r\n <g class=\"parallax\">\r\n <use xlink:href=\"#gentle-wave\" x=\"48\" y=\"0\" fill=\"rgba(255,255,255,0.7)\" />\r\n <use xlink:href=\"#gentle-wave\" x=\"48\" y=\"3\" fill=\"rgba(255,255,255,0.5)\" />\r\n <use xlink:href=\"#gentle-wave\" x=\"48\" y=\"7\" fill=\"#fff\" />\r\n </g>\r\n </svg>\r\n </div>\r\n <!-- </ng-container> -->\r\n </div>\r\n\r\n <!-- Incoming call user details shown in model -->\r\n <div class=\"call-container-model p-3 text-white model-content call-container\" *ngIf=\"isClickExpand\">\r\n <div class=\"mb-2 user-info-section\" >\r\n <div class=\"text-center my-3\">\r\n <h3 class=\"text-white\">C2C -POINT {{selectedUserInfo?.pointName}}</h3>\r\n </div>\r\n <div class=\"mb-3\">\r\n <h5 class=\"text-white mb-1\">Name:</h5>\r\n <h4 class=\"text-white userName\">{{selectedUserInfo?.name}}</h4>\r\n </div>\r\n <div class=\"f-13\">\r\n <div class=\"row mb-3\">\r\n <div class=\"col-6 mb-2\">\r\n <div class=\"mb-1\">Number:</div>\r\n <div class=\"\">{{selectedUserInfo?.number}}</div>\r\n </div>\r\n <div class=\"col-6 mb-2\">\r\n <div class=\"mb-1\">Extension:</div>\r\n <div class=\"ml-2\">{{selectedUserInfo?.extension}}</div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"row mb-3\">\r\n <div class=\"col-12 mb-2\">\r\n <div class=\"me-2\">Email: </div>\r\n <div>{{selectedUserInfo?.email}}</div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"row mb-3\">\r\n <div class=\"col-12 mb-2\">\r\n <div class=\"me-2\">Subject:</div>\r\n <div class=\"ml-2 subject-text\" title=\"{{selectedUserInfo?.subject}}\">{{selectedUserInfo?.subject}}</div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"row mb-3\">\r\n <div class=\"col-12 mb-2\">\r\n <div class=\"me-2 mb-1\">Image:</div>\r\n <div class=\"text-ellipsis\">\r\n <ng-container *ngIf=\"selectedUserInfo?.image && selectedUserInfo?.image !== '-'; else noImage\">\r\n <img src=\"{{selectedUserInfo?.image}}\" alt=\"\" width=\"150\" class=\"ml-2\"/>\r\n </ng-container>\r\n <ng-template #noImage>\r\n <span class=\"ml-2\">No Image Available</span>\r\n </ng-template>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\" mb-4\">\r\n <div class=\"\">\r\n <div class=\"mb-1\">Message:</div>\r\n <div>\r\n <div class=\"text-container\" [class.expanded]=\"isExpanded\">{{selectedUserInfo?.message}}</div>\r\n <small class=\"toggle-btn\" *ngIf=\"showButton\" (click)=\"toggleText()\">{{ isExpanded ? 'See less' : 'See more' }}</small>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"row mb-3\">\r\n <div class=\"col-6 mb-2\">\r\n <div class=\"mb-1\">Point Name:</div>\r\n <div class=\"\">{{selectedUserInfo?.pointName}}</div>\r\n </div>\r\n <div class=\"col-6 mb-2\">\r\n <div class=\"mb-1\">Source Name:</div>\r\n <div class=\"\">{{selectedUserInfo?.sourceName}}</div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- contact list panel -->\r\n <div class=\"contacts-panel\" *ngIf=\"showContactsPanel\">\r\n <div class=\"contacts-header\">\r\n <div class=\"title\">Participent</div>\r\n <div class=\"d-flex justify-content-between\">\r\n <p></p>\r\n <span class=\"material-symbols-outlined dial-close-btn\" (click)=\"toggleContactsPanel({}, true)\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\" width=\"24px\" fill=\"#000000\"><path d=\"m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z\"/></svg>\r\n </span>\r\n </div>\r\n </div>\r\n\r\n <!-- SEARCH INPUT (visible when isSearchVisible = true) -->\r\n <div class=\"search-bar p-3\">\r\n <input type=\"text\" placeholder=\"Search...\" [(ngModel)]=\"searchText\" (input)=\"applyFilter()\" />\r\n <ng-container *ngFor=\"let c of filteredList\">\r\n <div class=\"contact-item\" *ngIf=\"isDirectCallOptionShow && searchText\">\r\n <img class=\"contact-avatar\" [src]=\"c?.img || 'assets/images/user.jpg'\" alt=\"\" />\r\n <div class=\"contact-info\">\r\n <div class=\"contact-name\">{{c?.firstName}} {{c?.middleName}} {{c?.lastName}}</div>\r\n <div class=\"contact-title\">{{ (c?.numbersList && c?.numbersList[0]?.number)}}</div>\r\n </div>\r\n <button class=\"contact-call-btn contact-add-btn mr-2\" (click)=\"callContact(c)\" *ngIf=\"!c?.IsConnected\" title=\"Add to conference call\">\r\n <span class=\"material-symbols-outlined\"> add </span>\r\n </button>\r\n <button class=\"contact-call-btn\" (click)=\"CallToUnsavedNumber(c?.numbersList[0]?.number, true)\" *ngIf=\"!c?.IsConnected\" title=\"New Call\">\r\n <span class=\"material-symbols-outlined\"> call </span>\r\n </button>\r\n </div>\r\n </ng-container>\r\n <ng-container *ngIf=\"!filteredList.length\">\r\n <div class=\"contact-item\" *ngIf=\"searchText\">\r\n <img class=\"contact-avatar\" [src]=\"'assets/images/user.jpg'\" alt=\"\" />\r\n <div class=\"contact-info\">\r\n <div class=\"contact-title\">{{ searchText }}</div>\r\n </div>\r\n <button class=\"contact-call-btn contact-add-btn mr-2\" (click)=\"callContact(searchText, true)\" title=\"Add to conference call\">\r\n <span class=\"material-symbols-outlined\"> add </span>\r\n </button>\r\n <button class=\"contact-call-btn\" (click)=\"CallToUnsavedNumber(searchText, true)\" title=\"New Call\">\r\n <span class=\"material-symbols-outlined\"> call </span>\r\n </button>\r\n </div>\r\n </ng-container>\r\n </div>\r\n <div class=\"contacts-list\">\r\n <div class=\"px-2\">\r\n <h5 class=\"mb-0 title\">In This Call</h5>\r\n </div>\r\n <hr class=\"mb-2 mt-1\">\r\n <div class=\"contact-item\" *ngFor=\"let c of filteredParticipentList\">\r\n <ng-container *ngIf=\"c?.to == 'client' else participentInfo\">\r\n <img class=\"contact-avatar\" [src]=\"c?.fromImage || 'assets/images/user.jpg'\" alt=\"\" />\r\n <div class=\"contact-info\">\r\n <div class=\"contact-name\">You\r\n </div>\r\n <div class=\"contact-title\">{{ c?.from }}</div>\r\n </div>\r\n <button class=\"mic-btn mr-2\" [disabled]=\"c?.hold\"\r\n (click)=\"onMuteUser(c)\">\r\n <span class=\"material-symbols-outlined\" *ngIf=\"c?.isMute\"> mic_off </span>\r\n <span class=\"material-symbols-outlined\" *ngIf=\"!c?.isMute\"> mic </span>\r\n </button>\r\n <button class=\"conference-hold-contact mr-2\" [ngClass]=\"{ 'on-hold': c?.hold }\" (click)=\"onHoldCall(c)\">\r\n <span class=\"material-symbols-outlined\" [title]=\"!c?.hold ? 'Hold' : 'Resume'\"> phone_paused </span>\r\n </button>\r\n <button class=\"conference-contact\" (click)=\"onEndCall(c, false, true)\">\r\n <span class=\"material-symbols-outlined\" title=\"Call End\"> call_end </span>\r\n </button>\r\n </ng-container>\r\n <ng-template #participentInfo>\r\n <img class=\"contact-avatar\" [src]=\"c?.direction == 'outgoing-call' ? c?.toImage : c?.fromImage || 'assets/images/user.jpg'\" alt=\"\" />\r\n <div class=\"contact-info\">\r\n <div class=\"contact-name\">{{c?.direction == 'outgoing-call' ? c?.toName || 'Unknown' : c?.fromName || 'Unknown'}}\r\n </div>\r\n <div class=\"contact-title\">{{ c?.direction == 'outgoing-call' ? c?.to || 'Unknown' : c?.from ||\r\n 'Unknown'}}</div>\r\n <div class=\"d-flex\" *ngIf=\"c?.from == hostnumber?.from\">\r\n <span class=\"organizer-label\">Organizer</span>\r\n </div>\r\n </div>\r\n <button class=\"mic-btn mr-2\" [disabled]=\"c?.hold\"\r\n (click)=\"onMuteUser(c)\">\r\n <span class=\"material-symbols-outlined\" *ngIf=\"c?.isMute\"> mic_off </span>\r\n <span class=\"material-symbols-outlined\" *ngIf=\"!c?.isMute\"> mic </span>\r\n </button>\r\n <button class=\"conference-hold-contact mr-2\" [ngClass]=\"{ 'on-hold': c?.hold }\" (click)=\"onHoldCall(c)\">\r\n <span class=\"material-symbols-outlined\" [title]=\"!c?.hold ? 'Hold' : 'Resume'\"> phone_paused </span>\r\n </button>\r\n <button class=\"conference-contact\" (click)=\"onEndCall(c, false, true)\">\r\n <span class=\"material-symbols-outlined\" title=\"Call End\"> call_end </span>\r\n </button>\r\n </ng-template>\r\n </div>\r\n <hr class=\"m-2\">\r\n <div class=\"mt-3 px-2\">\r\n <h5 class=\"mb-0 title\">Participent added to the call</h5>\r\n </div>\r\n <hr class=\"mb-2 mt-1\"> \r\n <ng-container *ngFor=\"let c of filteredList\">\r\n <div class=\"contact-item\" *ngIf=\"!c?.IsConnected && false\">\r\n <img class=\"contact-avatar\" [src]=\"c?.img ? c?.img : 'assets/images/user.jpg'\" alt=\"\" />\r\n <div class=\"contact-info\">\r\n <div class=\"contact-name\">{{c?.firstName}} {{c?.middleName}} {{c?.lastName}}</div>\r\n <div class=\"contact-title\">{{ (c?.numbersList && c?.numbersList[0]?.number)}}</div>\r\n </div>\r\n <button class=\"contact-call-btn\" (click)=\"callContact(c)\" *ngIf=\"!c?.IsConnected\">\r\n <span class=\"material-symbols-outlined\"> call </span>\r\n <span class=\"label\">Call</span>\r\n </button>\r\n <button class=\"conference-hold-contact mr-2\" [ngClass]=\"{ 'on-hold': c?.hold }\" (click)=\"onHoldCall(c)\" *ngIf=\"c?.IsConnected\">\r\n <span class=\"material-symbols-outlined\" title=\"Hold\"> phone_paused </span>\r\n </button>\r\n <button class=\"conference-contact\" (click)=\"onEndCall(c, false, true)\" *ngIf=\"c?.IsConnected\">\r\n <span class=\"material-symbols-outlined\" title=\"Call End\"> call_end </span>\r\n </button>\r\n </div>\r\n </ng-container>\r\n <ng-container *ngFor=\"let c of leftParticipent[currentCall?.conferenceId]\">\r\n <div class=\"contact-item\">\r\n <img class=\"contact-avatar\" [src]=\"c.direction == 'outgoing-call' && c?.toImage ? c?.toImage : c?.fromImage || 'assets/images/user.jpg'\" alt=\"\" />\r\n <div class=\"contact-info\">\r\n <div class=\"contact-name\">{{c.direction == 'outgoing-call' ? c?.toName : c?.fromName || 'Unknown number'}}</div>\r\n <div class=\"contact-title\">{{c.direction == 'outgoing-call' ? c?.to : c?.from}}</div>\r\n </div>\r\n <button class=\"contact-call-btn contact-add-btn \" (click)=\"CallToUnsavedNumber(c.direction == 'outgoing-call' ? c?.to : c?.from)\" >\r\n <span class=\"material-symbols-outlined\"> add </span>\r\n <span class=\"label\">Add</span>\r\n </button>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div class=\"min-call-container\" *ngIf=\"isMinimised\">\r\n <span class=\"material-symbols-outlined fullscreen\" (click)=\"maximiseDialpad()\"> open_in_full </span>\r\n <div style=\"display: flex; width: 100%\">\r\n <div>\r\n <div class=\"min-call-animation\" id=\"call-avatar\">\r\n <img class=\"min-avatar-img\" [src]=\"callData.img\" alt=\"\" />\r\n </div>\r\n </div>\r\n <div>\r\n <div class=\"min-callerDetails\">\r\n <div class=\"name\">\r\n {{callData.name}}\r\n </div>\r\n <p style=\"margin: 0\">{{callData.displayNum ? callData.displayNum : callData.phone }}</p>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"min-btn-container\">\r\n <div class=\"min-timer\">{{timer}}</div>\r\n <button class=\"min-call-sec-btn\" (click)=\"toggleMute()\" [disabled]=\"disbaleEndCallBtn\">\r\n <span class=\"material-symbols-outlined\" *ngIf=\"isMute\"> mic_off </span>\r\n <span class=\"material-symbols-outlined\" *ngIf=\"!isMute\"> mic </span>\r\n </button>\r\n <button class=\"min-call-btn end-call-btn\" [disabled]=\"disbaleEndCallBtn\" (click)=\"endCall()\">\r\n <span class=\"material-symbols-outlined\"> call_end </span>\r\n </button>\r\n </div>\r\n</div>", styles: [".call-container{width:385px;height:646px!important;margin:auto;border-radius:20px;box-shadow:6px 6px 10px -1px #00000026,-5px -4px 10px -1px #00000026;display:flex;box-sizing:border-box;position:relative;justify-content:center;align-items:center;z-index:1000;flex-flow:column;overflow:hidden}.call-to-text{padding:6px 10px;border:1px solid #c2c2c2;border-radius:20px;font-size:13px}.collops{height:660px!important}.incoming-call-container{flex-flow:row!important}.active-call{width:385px!important}.call-animation{background:#fff;width:100px;height:100px;position:relative;margin:20px auto 0;border-radius:100%;border:solid 4px #fff;display:flex;align-items:center;justify-content:center}.call-animation:before{position:absolute;content:\"\";top:0;left:0;width:100%;height:100%;backface-visibility:hidden;border-radius:50%}.call-animation-play{animation:play 3s linear infinite}.call-info-wrapper{height:20px;overflow-y:auto;background:white;transition:height 1s}.open-collops{height:180px!important}.avatar-img{width:94px;height:94px;border-radius:100%}@keyframes play{0%{transform:scale(1)}15%{box-shadow:0 0 0 2px #fff6}25%{box-shadow:0 0 0 4px #fff6,0 0 0 8px #fff3}25%{box-shadow:0 0 0 8px #fff6,0 0 0 16px #fff3}50%{box-shadow:0 0 0 10px #fff6,0 0 0 20px #fff3}to{box-shadow:0 0 0 10px #fff6,0 0 0 20px #fff3;transform:scale(1.1);opacity:0}}.callerDetails{margin-top:8px;color:#fff;display:flex;flex-direction:column;align-items:center}.togglearrow-arrow{left:100%;background-color:#fff;width:25px;height:25px;text-align:center;cursor:pointer;border:1px solid #ccc;border-radius:50%;line-height:22px}.togglearrow-arrow.disabled{opacity:.3;cursor:not-allowed;pointer-events:none}.search-bar input{width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;outline:none;margin-bottom:10px}.togglearrow-arrow.disabled:hover{opacity:.3;cursor:not-allowed}.callerDetails h1{width:260px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin:12px 0 0;color:#fff;text-transform:capitalize;text-align:center}.callerDetails h4{margin:0;color:#fff}.tx-black,.title{color:#000!important}.callerDetails p{margin-top:-3px;margin-bottom:0;color:#fff}.call-sec-btn,.mic-btn{position:relative;box-sizing:border-box;border:1px solid #cccbcb;background-color:transparent;border-radius:25px;padding:12px;box-shadow:6px 6px 10px -1px #bebebe26,-5px -4px 10px -1px #d2d2d226;width:50px;height:50px}.mic-btn{padding:5px;width:37px;height:37px}.receive-btn{background-color:#28a745!important;color:#fff!important}.receive-btn span{color:#fff!important}.scroll-container{width:100%;overflow:hidden;white-space:nowrap;position:relative}.scroll-text{display:inline-block;padding-left:100%;animation:scroll-left 12s linear infinite;font-size:16px}@keyframes scroll-left{0%{transform:translate(0)}to{transform:translate(-100%)}}.call-sec-btn span{color:#cccbcb}.call-btn{width:60px;height:60px;background-color:#fff;border-radius:30px;box-sizing:border-box;border:2px solid white;margin:0 16px}.end-call-btn{background-color:#e14e4e}.end-call-btn span{color:#fff!important}.call-btn span{color:#234de8}.btn-container{display:flex;flex-wrap:wrap;padding:0 30px}.key-btn{width:50px;height:50px;background-color:transparent;text-align:center;box-sizing:border-box;margin:0 18px;font-size:22px;display:flex;flex-direction:column;justify-content:center;align-items:center;font-family:Lato,sans-serif;font-weight:900;font-style:normal;color:#d3d3d3;cursor:pointer;opacity:.8}.call-action-btns{text-align:center}#call-input{background-color:transparent;border:none;outline:none;text-align:center;color:#fff}.sendDigit{position:relative;text-align:center;width:80%;margin:auto;background-color:#ffffff1a;padding:2px 0;border-radius:3px}.input-clear-btn{position:absolute;right:6px;color:#fff;cursor:pointer}#minimize-btn-div{position:absolute;right:14px;top:12px;z-index:10}.minimize-btn{color:#fff;cursor:pointer}.wave-container{position:absolute;bottom:-4px;overflow:hidden;width:100%}.waves{width:660px;position:relative;margin-bottom:-7px;height:40px;min-height:40px}.held-call-banner{position:absolute;top:0;left:0;right:0;background:#1644f09c;z-index:2100;box-shadow:0 4px 12px #0000004d;border-radius:0 0 16px 16px;max-height:220px;overflow-y:auto}.held-call-content{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:6px 6px 0;padding-bottom:6px;border-bottom:1px dotted #4b4b4b}.held-info{display:flex;align-items:center;gap:10px;flex:1}.hold-icon{font-size:24px;color:#fbbf24}.swap-icon{font-size:24px}.held-caller{display:flex;flex-direction:column;gap:2px}.held-label{font-size:10px;color:#ffffffb3;text-transform:uppercase;letter-spacing:.5px}.held-name{font-size:14px;font-weight:600;color:#fff}.held-number{font-size:13px;font-weight:500;color:#fff}.held-actions{display:flex;gap:8px;align-items:center}.held-btn{padding:6px 16px;border-radius:20px;border:none;font-size:13px;font-weight:600;cursor:pointer;transition:transform .2s,box-shadow .2s}.held-btn:hover{transform:scale(1.05);box-shadow:0 4px 12px #0003}.swap-btn{background:#3b82f6;color:#fff}.merge-btn{background:#10b981;color:#fff}.h-77px{height:77px}.incoming-banners-container{width:100%;padding:5px 8px;height:100%;gap:8px;overflow-y:auto}.call-container-model{width:385px!important;height:646px!important;margin:auto 0 0 1px;border-radius:20px;box-shadow:6px 6px 10px -1px #00000026,-5px -4px 10px -1px #00000026;display:flex;box-sizing:border-box;position:relative;overflow:hidden;justify-content:center;align-items:center}.incoming-banner{top:0;left:0;width:100%;right:0;background:linear-gradient(135deg,#1e3a8a 0%,#3b82f6 100%);padding:12px 16px;z-index:2000;box-shadow:0 4px 12px #0003;border-radius:16px}.incoming-banner-content{display:flex;align-items:center;justify-content:space-between;gap:12px}.incoming-info{flex:1;display:flex;flex-direction:column;gap:4px}.incoming-label{font-size:11px;color:#fffc;text-transform:uppercase;letter-spacing:.5px}.incoming-caller{display:flex;flex-direction:column;gap:2px}.caller-name{font-size:15px;font-weight:600;color:#fff}.caller-number{font-size:13px;color:#ffffffe6}.incoming-actions{display:flex;gap:8px;align-items:center}.banner-btn{width:44px;height:44px;border-radius:50%;border:none;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:transform .2s}.banner-btn:hover{transform:scale(1.1)}.banner-btn .material-symbols-outlined{font-size:20px}.accept-btn{background:#10b981}.accept-btn .material-symbols-outlined{color:#fff}.reject-btn{background:#ef4444}.reject-btn .material-symbols-outlined{color:#fff}.contacts-panel{position:absolute;top:0;bottom:12px;width:340px;background:#ffffff;border-radius:16px;box-shadow:0 10px 25px #00000026;display:flex;flex-direction:column;overflow:hidden;height:40.4rem;left:24.1rem;z-index:1000000}.contacts-header{height:56px;display:flex;align-items:center;justify-content:space-between;padding:0 16px;border-bottom:1px solid #f0f0f0}.contacts-header .title{font-weight:600}.contacts-header .back,.contacts-header .search{color:#9aa0a6;cursor:pointer}.disabled{opacity:.5;pointer-events:none}.contacts-list{padding:8px 8px 12px;overflow-y:auto}.contact-item{display:flex;align-items:center;padding:10px 8px;border-radius:10px}.contact-item:hover{background:#f7f9fc}.contact-avatar{width:37px;height:37px;border-radius:50%;object-fit:cover;margin-right:12px}.contact-info{flex:1}.contact-name{font-weight:600;color:#111827}.contact-title{font-size:12px;color:#6b7280}.contact-call-btn{display:inline-flex;align-items:center;gap:6px;background:#234de8;color:#fff;border:none;border-radius:16px;padding:8px;cursor:pointer}.contact-add-btn{background-color:#2ecc71!important}.conference-hold-contact{display:inline-flex;align-items:center;gap:5px;background:#727070;color:#fff;border:none;border-radius:50%;padding:7px;cursor:pointer}.conference-hold-contact.on-hold{background:#28a745!important;color:#fff}.user-info-section{width:100%;height:100%;overflow-y:auto;overflow-x:hidden!important}.user-info-section::-webkit-scrollbar{display:none}.toggle-btn{cursor:pointer}.text-container{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;transition:all .3s ease}.text-container.expanded{-webkit-line-clamp:unset}.userName{font-family:FontAwesome}.subject-text{display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden}.conference-contact{display:inline-flex;align-items:center;gap:5px;background:#e14e4e;color:#fff;border:none;border-radius:50%;padding:7px;cursor:pointer}.organizer-label{padding:1px 5px;font-size:11px;border-radius:10px;border:1px solid #a0a0a0;margin-top:2px;background:#fcfcfc}.contact-call-btn .material-symbols-outlined{font-size:18px;color:#fff}.contact-call-btn .label{font-size:12px}.parallax>use{animation:move-forever 25s cubic-bezier(.55,.5,.45,.5) infinite}.parallax>use:nth-child(1){animation-delay:-2s;animation-duration:7s}.parallax>use:nth-child(2){animation-delay:-3s;animation-duration:10s}.parallax>use:nth-child(3){animation-delay:-4s;animation-duration:13s}.parallax>use:nth-child(4){animation-delay:-5s;animation-duration:20s}@keyframes move-forever{0%{transform:translate3d(-90px,0,0)}to{transform:translate3d(85px,0,0)}}.animated-margin{transition:margin-top .5s ease}app-incoming-call{position:absolute;top:0;left:0;width:100%;height:100%;background-color:transparent;z-index:1001}.min-call-container{width:320px;height:124px;border-radius:20px;box-shadow:6px 6px 10px -1px #00000026,-5px -4px 10px -1px #00000026;display:flex;flex-direction:column;box-sizing:border-box;position:relative;overflow:hidden;margin:auto;align-items:center;padding:12px 16px;color:#fff}.min-call-animation{background:#fff;width:48px;height:48px;position:relative;margin:0 12px 0 auto;border-radius:100%;border:solid 2px #fff}.min-avatar-img{width:46px;height:46px;border-radius:100%;position:absolute;left:0;top:0}.min-callerDetails{color:#fff;display:flex;flex-direction:column;align-items:flex-start}.name{width:170px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:20px;margin:0;color:#fff}.min-callerDetails p{margin:0;color:#fff}.min-btn-container{position:relative;display:flex;width:100%;justify-content:flex-start;align-items:center;margin-top:6px}.min-call-sec-btn{width:40px;height:40px;box-sizing:border-box;border:1px solid #cccbcb;background-color:transparent;border-radius:20px;display:flex;align-items:center;justify-content:center;margin-right:12px;box-shadow:6px 6px 10px -1px #bebebe26,-5px -4px 10px -1px #d2d2d226}.min-call-sec-btn span{color:#cccbcb}.min-call-btn{width:40px;height:40px;border-radius:20px;box-sizing:border-box;border:2px solid white;display:flex;align-items:center;justify-content:center}.fullscreen{position:absolute;right:18px;top:14px;color:#e8e8e8;font-size:18px;cursor:pointer}.btn-container{display:flex;flex-wrap:wrap;padding:0 24px}.dial-btn{width:40px;height:40px;background-color:transparent;text-align:center;box-sizing:border-box;margin:4px 25px;font-size:24px;display:flex;flex-direction:column;justify-content:center;align-items:center;font-family:Lato,sans-serif;font-weight:900;font-style:normal;color:#b5b5b5;cursor:pointer}.btn-albhabets{font-family:Lato,sans-serif;font-size:12px;font-weight:400}.min-timer{width:50px;font-size:18px;margin-right:10px;border-radius:4px;height:35px;display:flex;align-items:center}.record-action-btns{display:flex;flex-direction:column;align-items:center}.record-btn-container{position:relative}.record-btn{border:none;border-radius:50%;width:50px;height:50px;display:flex;align-items:center;justify-content:center;cursor:pointer;margin:0 5px;position:relative;overflow:hidden}.record-btn.start-stop .recording-icon{width:50%;height:50%;border-radius:50%;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}.record-btn.start-stop.recording .recording-icon{background-color:#000}.record-btn.start-stop.recording{border:3px solid #000}.record-btn.start-stop.stopped .recording-icon{background-color:red;border:3px solid #ff0000;border-radius:50%;position:absolute}.record-btn.start-stop.stopped{border:3px solid #ff0000}.record-btn.start-stop.stopped .recording-icon{width:40%;height:40%;border-radius:0;background-color:red}.pause-resume-btns{display:flex;flex-direction:column;align-items:center;margin-top:10px}.record-btn.pause-resume{border:none;border-radius:50%;width:50px;height:50px;background:white;display:flex;align-items:center;justify-content:center;margin:5px 0}.record-btn.pause-resume .material-symbols-outlined{font-size:20px;color:#000}.timer-display{font-size:1.2em;margin-top:10px;color:#000}.w-40{width:40%}.w-60{width:60%}.callToNum{color:#fff;font-weight:400;text-align:center}.callToNum span{font-weight:600}.conference-call-view{display:flex;flex-direction:column;align-items:center;justify-content:flex-start;width:100%;padding:12px 16px 35px;color:#fff;height:100%}.conf-heading{display:flex;align-items:center;gap:8px;margin-top:8px}.conf-icon{color:#4579aa;font-size:32px;width:50px;height:50px;border:1px solid gray;border-radius:50%;display:flex;align-items:center;justify-content:center;background:#e1e1e1}.conf-title{font-weight:600;font-size:20px}.conf-name{margin-top:10px;font-size:17px;font-weight:600;text-align:center}.conf-timer{margin-top:4px;font-size:12px;opacity:.9}.conf-record{margin-top:14px}.record-stop-btn{width:44px;height:44px;border-radius:50%;border:none;background:#fff;display:flex;align-items:center;justify-content:center}.record-stop-btn .material-symbols-outlined{color:#e14e4e;font-size:28px}.conf-remove{margin-top:8px}.remove-btn{background:#ff0000!important;color:#fff;border:none;border-radius:6px;padding:6px 12px;font-size:12px;width:82px!important;height:auto}.conf-actions{margin-top:14px;display:flex;align-items:center;justify-content:center;gap:18px}.circle-btn{width:56px;height:56px;border-radius:50%;border:none;background:#000;display:flex;align-items:center;justify-content:center}.circle-btn .material-symbols-outlined{color:#fff;font-size:24px}.circle-btn.active{opacity:.85}.conf-end{margin-top:16px}.circle-btn.danger{background:#e14e4e}.circle-btn.danger .material-symbols-outlined{color:#fff}\n"], dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i6.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
|
|
3222
|
+
CallProgressComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: CallProgressComponent, selector: "lib-call-progress", inputs: { callData: "callData", selectedCallerId: "selectedCallerId", newIncomingCallData: "newIncomingCallData", newIncomingCallsList: "newIncomingCallsList", callerIdList: "callerIdList", deviceId: "deviceId", conferenceCallInfo: "conferenceCallInfo" }, outputs: { endCallEvent: "endCallEvent", incomingCallsNewInfo: "incomingCallsNewInfo", minimiseEvent: "minimiseEvent", incomingCallInitiated: "incomingCallInitiated", isLoadershow: "isLoadershow", endIncomingCallEvent: "endIncomingCallEvent" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"d-flex\">\r\n <div class=\"call-container\" *ngIf=\"!isMinimised && currentCallList?.length\"\r\n [ngClass]=\"{'collops': isCollops, 'incoming-call-container': isClickExpand, 'contacts-open': showContactsPanel }\">\r\n <!-- <ng-container *ngIf=\"!incomingCallDiv || isConcurrentIncoming || true\"> -->\r\n\r\n <!-- All type Call Hold list -->\r\n <div class=\"held-call-banner\"\r\n *ngIf=\"currentCallList.length > 1 && !!currentCall && ((isConferenceCallHold || isConference) || !isConference)\">\r\n <ng-container *ngFor=\"let conf of conferenceCallList\">\r\n <div class=\"held-call-content\" *ngIf=\"conf?.isConferenceHold\">\r\n <div class=\"held-info\">\r\n <span class=\"material-symbols-outlined hold-icon\">pause_circle</span>\r\n <div class=\"held-caller\">\r\n <span class=\"held-label\">Hold</span>\r\n <span class=\"held-name\">Conference Call</span>\r\n </div>\r\n </div>\r\n <div class=\"held-actions\">\r\n <button class=\"conference-hold-contact\" [ngClass]=\"{ 'on-hold': conf?.isConferenceHold }\"\r\n (click)=\"swapCalls(conf,true)\">\r\n <span class=\"material-symbols-outlined\" title=\"{{'Hold'}}\"> phone_paused </span>\r\n </button>\r\n <button class=\"conference-contact\" (click)=\"endCall(true)\">\r\n <span class=\"material-symbols-outlined\" title=\"Call End\"> call_end </span>\r\n </button>\r\n <div class=\"togglearrow-arrow me-2\" id=\"togglearrow\" (click)=\"toggleContactsPanel(conf)\">\r\n <i class=\"fa fa-angle-right\"></i>\r\n </div>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- For single incoming call -->\r\n <div class=\"h-100 py-5\" style=\"display: flex; flex-direction: column;\"\r\n *ngIf=\"currentCallList.length === 1 && currentCallList[0]?.isIncomingCall && !currentCallList[0]?.isAcceptCall \">\r\n <div class=\"callToNum\">Incoming call on <br /><span>{{currentCallList[0]?.to || 'Unknown\r\n Number'}}</span>\r\n </div>\r\n <div class=\"call-animation\" [ngClass]=\"{'call-animation-play': showRingAnimation}\">\r\n <img class=\"avatar-img\" [src]=\"currentCallList[0]?.img || 'assets/images/user.jpg'\" alt=\"\"\r\n width=\"120\" />\r\n </div>\r\n <div class=\"callerDetails\">\r\n <h1>{{ currentCallList[0]?.name ? currentCallList[0]?.name : currentCallList[0]?.phone || 'Unknown\r\n Number' }}</h1>\r\n <p *ngIf=\"!!currentCallList[0]?.name\">{{ currentCallList[0]?.phone }}</p>\r\n </div>\r\n\r\n <div class=\"call-action-btns mt-auto\">\r\n <button class=\"call-btn receive-btn\" *ngIf=\"!newIncomingCallsList[0]?.isCallConnected\"\r\n [disabled]=\"isIncomingCallBtnDisable\">\r\n <span class=\"material-symbols-outlined\" (click)=\"add(currentCallList[0])\"> call </span>\r\n </button>\r\n <button class=\"call-btn reject-btn\">\r\n <span class=\"material-symbols-outlined\" (click)=\"onEndCall(currentCallList[0])\"> call_end\r\n </span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- For single active call -->\r\n <div *ngIf=\"(!isConference || isConferenceCallHold) && (!!currentCall?.id && !currentCall?.isConference) && currentCall?.isAcceptCall\"\r\n [ngStyle]=\"{'display': 'flex', 'flex-direction': 'column', 'position': 'relative'}\" class=\"active-call\">\r\n\r\n <div class=\"call-animation\" [ngClass]=\"{'call-animation-play': showRingAnimation}\">\r\n <img class=\"avatar-img\" [src]=\"currentCall?.img || 'assets/images/user.jpg'\" alt=\"\" width=\"120\" />\r\n </div>\r\n <div class=\"callerDetails\">\r\n <h1 [ngStyle]=\"{'margin-top': showKeypad ? '0': '8px'}\">{{currentCall?.name || 'Unknown number'}}\r\n </h1>\r\n <p>{{currentCall?.phone }}</p>\r\n <h4 style=\"margin-top: 4px\">{{currentCall?.time || timer}}</h4>\r\n </div>\r\n\r\n <div class=\"record-action-btns\" *ngIf=\"!showKeypad\" [ngStyle]=\"{'margin-top': showKeypad ? '0': '20px'}\">\r\n <div class=\"record-btn-container\">\r\n <button class=\"record-btn start-stop\" *ngIf=\"!isRecording\"\r\n [ngClass]=\"{'recording': isRecording, 'stopped': !isRecording}\" (click)=\"toggleRecording()\"\r\n [title]=\"isRecording ? 'Stop Recording' : 'Start Recording'\"\r\n [disabled]=\"!currentCall?.isAcceptCall\">\r\n <span class=\"recording-icon\"></span>\r\n </button>\r\n <div class=\"pause-resume-btns\">\r\n <button class=\"record-btn pause-resume\" *ngIf=\"isRecording && !isPaused\"\r\n (click)=\"pauseRecording()\">\r\n <span class=\"material-symbols-outlined\"> pause </span>\r\n </button>\r\n <button class=\"record-btn pause-resume\" *ngIf=\"isPaused\" (click)=\"resumeRecording()\">\r\n <span class=\"material-symbols-outlined\"> play_arrow </span>\r\n </button>\r\n </div>\r\n </div>\r\n <div *ngIf=\"isRecording\" class=\"timer-display\">\r\n {{ getFormattedTime() }}\r\n </div>\r\n </div>\r\n <div *ngIf=\"showKeypad\" class=\"sendDigit\">\r\n <input type=\"text\" name=\"call-inputs\" id=\"call-input\" [(ngModel)]=\"callInput\"\r\n (keyup)=\"onCallInputEnter($event)\">\r\n <span class=\"material-symbols-outlined input-clear-btn\" *ngIf=\"callInput\"\r\n (click)=\"clearInputs()\">close_small</span>\r\n </div>\r\n <div class=\"btn-container justify-content-center\" *ngIf=\"showKeypad\">\r\n <div class=\"key-btn\" *ngFor=\"let key of keypadVal\" (click)=\"onCallInputs(key.num)\">\r\n {{key.num}}\r\n <span class=\"btn-albhabets\">{{key.text ? key.text : ' '}}</span>\r\n </div>\r\n </div>\r\n\r\n <div class=\"call-action-btns\" [ngStyle]=\"{'margin-top': showKeypad ? '0': '723x'}\">\r\n <!-- <div class=\"mb-3\" *ngIf=\"!incomingCallDiv || isConcurrentIncoming\">\r\n <button class=\"held-btn merge-btn\" (click)=\"mergeCalls()\" title=\"Merge calls\"\r\n [disabled]=\"isMergeCallAllowed() || currentCallList.length < 2\">\r\n <span>Merge</span>\r\n </button>\r\n </div> -->\r\n <div class=\"flex align-items-center justify-content-evenly mb-3\">\r\n <button class=\"call-sec-btn mr-3\" [disabled]=\"!currentCall?.isAcceptCall\" (click)=\"toggleMute()\">\r\n <span class=\"material-symbols-outlined\" *ngIf=\"isMute\"> mic_off </span>\r\n <span class=\"material-symbols-outlined\" *ngIf=\"!isMute\"> mic </span>\r\n\r\n </button>\r\n <button class=\"call-sec-btn mr-3\" [disabled]=\"!currentCall?.isAcceptCall\">\r\n <span class=\"material-symbols-outlined\" (click)=\"toggleKeypad()\"> transition_dissolve\r\n </span>\r\n </button>\r\n <button class=\"call-sec-btn\" [disabled]=\"!currentCall?.isAcceptCall\"\r\n (click)=\"toggleContactsPanel(currentCall)\">\r\n <span class=\"material-symbols-outlined\"> groups_2 </span>\r\n </button>\r\n </div>\r\n\r\n <div>\r\n <button class=\"call-btn end-call-btn\" [disabled]=\"!currentCall?.isAcceptCall\" (click)=\"endCall()\">\r\n <span class=\"material-symbols-outlined\"> call_end </span>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- conference call view -->\r\n <div class=\"conference-call-view\" *ngIf=\"isConference && currentCall?.isConference\">\r\n <div class=\"conf-heading\">\r\n <span class=\"conf-icon material-symbols-outlined\"> groups </span>\r\n <span class=\"conf-title\">Conference Call</span>\r\n </div>\r\n\r\n <div class=\"scroll-container\">\r\n <div class=\"scroll-text conf-name\">\r\n <ng-container *ngFor=\"let call of currentCallList; let i = index\">\r\n <ng-container *ngIf=\"!call?.isConferenceHold\">\r\n <span *ngIf=\"i != 0\">&</span>\r\n {{call?.name ? call?.name : call?.phone || 'Unknown number'}}\r\n </ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n <div class=\"conf-timer\">{{ timer }}</div>\r\n <div class=\"record-action-btns mt-auto\" *ngIf=\"!showKeypad\"\r\n [ngStyle]=\"{'margin-top': showKeypad ? '0': '20px'}\">\r\n <div class=\"record-btn-container\">\r\n <button class=\"record-btn start-stop\" *ngIf=\"!isRecording\"\r\n [ngClass]=\"{'recording': isRecording, 'stopped': !isRecording}\" (click)=\"toggleRecording()\"\r\n [title]=\"isRecording ? 'Stop Recording' : 'Start Recording'\">\r\n <span class=\"recording-icon\"></span>\r\n </button>\r\n <div class=\"pause-resume-btns\">\r\n <button class=\"record-btn pause-resume\" *ngIf=\"isRecording && !isPaused\"\r\n (click)=\"pauseRecording()\">\r\n <span class=\"material-symbols-outlined\"> pause </span>\r\n </button>\r\n <button class=\"record-btn pause-resume\" *ngIf=\"isPaused\" (click)=\"resumeRecording()\">\r\n <span class=\"material-symbols-outlined\"> play_arrow </span>\r\n </button>\r\n </div>\r\n </div>\r\n <div *ngIf=\"isRecording\" class=\"timer-display\">\r\n {{ getFormattedTime() }}\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"showKeypad\" class=\"sendDigit mt-2\">\r\n <input type=\"text\" name=\"call-inputs\" id=\"call-input\" [(ngModel)]=\"callInput\"\r\n (keyup)=\"onCallInputEnter($event)\">\r\n <span class=\"material-symbols-outlined input-clear-btn\" *ngIf=\"callInput\"\r\n (click)=\"clearInputs()\">close_small</span>\r\n </div>\r\n <div class=\"btn-container justify-content-center\" *ngIf=\"showKeypad\">\r\n <div class=\"key-btn\" *ngFor=\"let key of keypadVal\" (click)=\"onCallInputs(key.num)\">\r\n {{key.num}}\r\n <span class=\"btn-albhabets\">{{key.text ? key.text : ' '}}</span>\r\n </div>\r\n </div>\r\n\r\n <div class=\"conf-actions\">\r\n <button class=\"circle-btn\" [ngClass]=\"{'active': isMute}\" (click)=\"toggleMute(true)\">\r\n <span class=\"material-symbols-outlined\"> {{ isMute ? 'mic_off' : 'mic' }} </span>\r\n </button>\r\n <button class=\"circle-btn\" (click)=\"toggleKeypad()\">\r\n <span class=\"material-symbols-outlined\"> transition_dissolve </span>\r\n </button>\r\n <button class=\"circle-btn\" (click)=\"toggleContactsPanel(currentCall)\">\r\n <span class=\"material-symbols-outlined\"> groups_2 </span>\r\n </button>\r\n </div>\r\n\r\n <div class=\"conf-end\">\r\n <button class=\"circle-btn danger\" (click)=\"endConfereneceCall()\">\r\n <span class=\"material-symbols-outlined\"> call_end </span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"wave-container\">\r\n <svg class=\"waves\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\r\n viewBox=\"0 24 150 28\" preserveAspectRatio=\"none\" shape-rendering=\"auto\">\r\n <defs>\r\n <path id=\"gentle-wave\"\r\n d=\"M-160 44c30 0 58-18 88-18s 58 18 88 18 58-18 88-18 58 18 88 18 v44h-352z\" />\r\n </defs>\r\n <g class=\"parallax\">\r\n <use xlink:href=\"#gentle-wave\" x=\"48\" y=\"0\" fill=\"rgba(255,255,255,0.7)\" />\r\n <use xlink:href=\"#gentle-wave\" x=\"48\" y=\"3\" fill=\"rgba(255,255,255,0.5)\" />\r\n <use xlink:href=\"#gentle-wave\" x=\"48\" y=\"7\" fill=\"#fff\" />\r\n </g>\r\n </svg>\r\n </div>\r\n <!-- </ng-container> -->\r\n </div>\r\n\r\n <!-- Incoming call user details shown in model -->\r\n <div class=\"call-container-model p-3 text-white model-content call-container\" *ngIf=\"isClickExpand\">\r\n <div class=\"mb-2 user-info-section\">\r\n <div class=\"text-center my-3\">\r\n <h3 class=\"text-white\">C2C -POINT {{selectedUserInfo?.pointName}}</h3>\r\n </div>\r\n <div class=\"mb-3\">\r\n <h5 class=\"text-white mb-1\">Name:</h5>\r\n <h4 class=\"text-white userName\">{{selectedUserInfo?.name}}</h4>\r\n </div>\r\n <div class=\"f-13\">\r\n <div class=\"row mb-3\">\r\n <div class=\"col-6 mb-2\">\r\n <div class=\"mb-1\">Number:</div>\r\n <div class=\"\">{{selectedUserInfo?.number}}</div>\r\n </div>\r\n <div class=\"col-6 mb-2\">\r\n <div class=\"mb-1\">Extension:</div>\r\n <div class=\"ml-2\">{{selectedUserInfo?.extension}}</div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"row mb-3\">\r\n <div class=\"col-12 mb-2\">\r\n <div class=\"me-2\">Email: </div>\r\n <div>{{selectedUserInfo?.email}}</div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"row mb-3\">\r\n <div class=\"col-12 mb-2\">\r\n <div class=\"me-2\">Subject:</div>\r\n <div class=\"ml-2 subject-text\" title=\"{{selectedUserInfo?.subject}}\">\r\n {{selectedUserInfo?.subject}}</div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"row mb-3\">\r\n <div class=\"col-12 mb-2\">\r\n <div class=\"me-2 mb-1\">Image:</div>\r\n <div class=\"text-ellipsis\">\r\n <ng-container\r\n *ngIf=\"selectedUserInfo?.image && selectedUserInfo?.image !== '-'; else noImage\">\r\n <img src=\"{{selectedUserInfo?.image}}\" alt=\"\" width=\"150\" class=\"ml-2\" />\r\n </ng-container>\r\n <ng-template #noImage>\r\n <span class=\"ml-2\">No Image Available</span>\r\n </ng-template>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\" mb-4\">\r\n <div class=\"\">\r\n <div class=\"mb-1\">Message:</div>\r\n <div>\r\n <div class=\"text-container\" [class.expanded]=\"isExpanded\">{{selectedUserInfo?.message}}\r\n </div>\r\n <small class=\"toggle-btn\" *ngIf=\"showButton\" (click)=\"toggleText()\">{{ isExpanded ? 'See\r\n less' : 'See more' }}</small>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"row mb-3\">\r\n <div class=\"col-6 mb-2\">\r\n <div class=\"mb-1\">Point Name:</div>\r\n <div class=\"\">{{selectedUserInfo?.pointName}}</div>\r\n </div>\r\n <div class=\"col-6 mb-2\">\r\n <div class=\"mb-1\">Source Name:</div>\r\n <div class=\"\">{{selectedUserInfo?.sourceName}}</div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- contact list panel -->\r\n <div class=\"contacts-panel\" *ngIf=\"showContactsPanel\">\r\n <div class=\"contacts-header\">\r\n <div>Participent</div>\r\n <div class=\"d-flex justify-content-between\">\r\n <p></p>\r\n <span class=\"material-symbols-outlined dial-close-btn\" (click)=\"toggleContactsPanel({}, true)\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\" width=\"24px\"\r\n fill=\"#000000\">\r\n <path\r\n d=\"m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z\" />\r\n </svg>\r\n </span>\r\n </div>\r\n </div>\r\n\r\n <!-- SEARCH INPUT (visible when isSearchVisible = true) -->\r\n <div class=\"search-bar p-3\">\r\n <input type=\"text\" placeholder=\"Search...\" [(ngModel)]=\"searchText\" (input)=\"applyFilter()\" />\r\n <ng-container *ngFor=\"let c of filteredList\">\r\n <div class=\"contact-item\" *ngIf=\"isDirectCallOptionShow && searchText\">\r\n <img class=\"contact-avatar\" [src]=\"c?.img || 'assets/images/user.jpg'\" alt=\"\" />\r\n <div class=\"contact-info\">\r\n <div class=\"contact-name\">{{c?.firstName}} {{c?.middleName}} {{c?.lastName}}</div>\r\n <div class=\"contact-title\">{{ (c?.numbersList && c?.numbersList[0]?.number)}}</div>\r\n </div>\r\n <button class=\"contact-call-btn contact-add-btn mr-2\" (click)=\"callContact(c)\"\r\n *ngIf=\"!c?.IsConnected\" title=\"Add to conference call\">\r\n <span class=\"material-symbols-outlined\"> add </span>\r\n </button>\r\n <button class=\"contact-call-btn\" (click)=\"CallToUnsavedNumber(c?.numbersList[0]?.number, true)\"\r\n *ngIf=\"!c?.IsConnected\" title=\"New Call\">\r\n <span class=\"material-symbols-outlined\"> call </span>\r\n </button>\r\n </div>\r\n </ng-container>\r\n <ng-container *ngIf=\"!filteredList.length\">\r\n <div class=\"contact-item\" *ngIf=\"searchText\">\r\n <img class=\"contact-avatar\" [src]=\"'assets/images/user.jpg'\" alt=\"\" />\r\n <div class=\"contact-info\">\r\n <div class=\"contact-title\">{{ searchText }}</div>\r\n </div>\r\n <button class=\"contact-call-btn contact-add-btn mr-2\" (click)=\"CallToUnsavedNumber(searchText)\"\r\n title=\"Add to conference call\">\r\n <span class=\"material-symbols-outlined\"> add </span>\r\n </button>\r\n <button class=\"contact-call-btn\" (click)=\"CallToUnsavedNumber(searchText, true)\" title=\"New Call\">\r\n <span class=\"material-symbols-outlined\"> call </span>\r\n </button>\r\n </div>\r\n </ng-container>\r\n </div>\r\n <div class=\"contacts-list\">\r\n <div class=\"px-2\">\r\n <h5 class=\"mb-0 title\">In This Call</h5>\r\n </div>\r\n <hr class=\"mb-2 mt-1\">\r\n <ng-container *ngFor=\"let c of filteredParticipentList\">\r\n <div class=\"contact-item\" *ngIf=\"!c?.isLeft\">\r\n <ng-container *ngIf=\"c?.to == 'client' else participentInfo\">\r\n <img class=\"contact-avatar\" [src]=\"c?.fromImage || 'assets/images/user.jpg'\" alt=\"\" />\r\n <div class=\"contact-info\">\r\n <div class=\"contact-name\">You\r\n </div>\r\n <div class=\"contact-title\">{{ c?.from }}</div>\r\n </div>\r\n <button class=\"mic-btn mr-2\" [disabled]=\"c?.hold\" (click)=\"onMuteUser(c)\">\r\n <span class=\"material-symbols-outlined\" *ngIf=\"c?.isMute\"> mic_off </span>\r\n <span class=\"material-symbols-outlined\" *ngIf=\"!c?.isMute\"> mic </span>\r\n </button>\r\n <button class=\"conference-hold-contact mr-2\" [ngClass]=\"{ 'on-hold': c?.hold }\"\r\n (click)=\"onHoldCall(c)\">\r\n <span class=\"material-symbols-outlined\" [title]=\"!c?.hold ? 'Hold' : 'Resume'\"> phone_paused\r\n </span>\r\n </button>\r\n <button class=\"conference-contact\" (click)=\"onEndCall(c, false, true)\">\r\n <span class=\"material-symbols-outlined\" title=\"Call End\"> call_end </span>\r\n </button>\r\n </ng-container>\r\n <ng-template #participentInfo>\r\n <img class=\"contact-avatar\"\r\n [src]=\"c?.direction == 'outgoing-call' ? c?.toImage || 'assets/images/user.jpg' : c?.fromImage || 'assets/images/user.jpg'\"\r\n alt=\"\" />\r\n <div class=\"contact-info\">\r\n <div class=\"contact-name\">{{c?.direction == 'outgoing-call' ? c?.toName || 'Unknown' :\r\n c?.fromName || 'Unknown'}}\r\n </div>\r\n <div class=\"contact-title\" *ngIf=\"c?.to != 'c2c_softphone_client'\">{{ c?.direction ==\r\n 'outgoing-call' ? c?.to || 'Unknown' : c?.from ||\r\n 'Unknown'}}</div>\r\n <div class=\"contact-title\" *ngIf=\"c?.to == 'c2c_softphone_client'\">{{ c?.from ||\r\n 'Unknown'}}</div>\r\n <div class=\"d-flex\" *ngIf=\"c?.from == hostnumber?.from && c?.to == 'c2c_softphone_client'\">\r\n <span class=\"organizer-label\">Organizer</span>\r\n </div>\r\n </div>\r\n <button class=\"mic-btn mr-2\" [disabled]=\"c?.hold\" (click)=\"onMuteUser(c)\">\r\n <span class=\"material-symbols-outlined\" *ngIf=\"c?.isMute\"> mic_off </span>\r\n <span class=\"material-symbols-outlined\" *ngIf=\"!c?.isMute\"> mic </span>\r\n </button>\r\n <button class=\"conference-hold-contact mr-2\" [ngClass]=\"{ 'on-hold': c?.hold }\"\r\n (click)=\"onHoldCall(c)\" *ngIf=\"c?.to != 'c2c_softphone_client'\">\r\n <span class=\"material-symbols-outlined\" [title]=\"!c?.hold ? 'Hold' : 'Resume'\"> phone_paused\r\n </span>\r\n </button>\r\n <button class=\"conference-contact\" (click)=\"onEndCall(c, false, true)\"\r\n *ngIf=\"(c?.to == 'c2c_softphone_client' && deviceNumberList.includes(c?.from)) || c?.to != 'c2c_softphone_client'\">\r\n <span class=\"material-symbols-outlined\" title=\"Call End\"> call_end </span>\r\n </button>\r\n </ng-template>\r\n </div>\r\n </ng-container>\r\n <hr class=\"m-2\">\r\n <div class=\"mt-3 px-2\">\r\n <h5 class=\"mb-0 title\">Participent added to the call</h5>\r\n </div>\r\n <hr class=\"mb-2 mt-1\">\r\n <ng-container *ngFor=\"let c of filteredParticipentList\">\r\n <div class=\"contact-item\" *ngIf=\"c?.isLeft\">\r\n <img class=\"contact-avatar\"\r\n [src]=\"c.direction == 'outgoing-call' ? c?.toImage || 'assets/images/user.jpg' : c?.fromImage || 'assets/images/user.jpg'\"\r\n alt=\"\" />\r\n <div class=\"contact-info\">\r\n <div class=\"contact-name\">{{c.direction == 'outgoing-call' ? c?.toName : c?.fromName || 'Unknown\r\n number'}}</div>\r\n <div class=\"contact-title\">{{c.direction == 'outgoing-call' ? c?.to : c?.from}}</div>\r\n </div>\r\n <button class=\"contact-call-btn contact-add-btn \"\r\n (click)=\"CallToUnsavedNumber(c.direction == 'outgoing-call' ? c?.to : c?.from)\">\r\n <span class=\"material-symbols-outlined\"> add </span>\r\n <span class=\"label\">Add</span>\r\n </button>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div class=\"min-call-container\" *ngIf=\"isMinimised\">\r\n <span class=\"material-symbols-outlined fullscreen\" (click)=\"maximiseDialpad()\"> open_in_full </span>\r\n <div style=\"display: flex; width: 100%\">\r\n <div>\r\n <div class=\"min-call-animation\" id=\"call-avatar\">\r\n <img class=\"min-avatar-img\" [src]=\"callData.img\" alt=\"\" />\r\n </div>\r\n </div>\r\n <div>\r\n <div class=\"min-callerDetails\">\r\n <div class=\"name\">\r\n {{callData.name}}\r\n </div>\r\n <p style=\"margin: 0\">{{callData.displayNum ? callData.displayNum : callData.phone }}</p>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"min-btn-container\">\r\n <div class=\"min-timer\">{{timer}}</div>\r\n <button class=\"min-call-sec-btn\" (click)=\"toggleMute()\" [disabled]=\"disbaleEndCallBtn\">\r\n <span class=\"material-symbols-outlined\" *ngIf=\"isMute\"> mic_off </span>\r\n <span class=\"material-symbols-outlined\" *ngIf=\"!isMute\"> mic </span>\r\n </button>\r\n <button class=\"min-call-btn end-call-btn\" [disabled]=\"disbaleEndCallBtn\" (click)=\"endCall()\">\r\n <span class=\"material-symbols-outlined\"> call_end </span>\r\n </button>\r\n </div>\r\n</div>\r\n<!-- Call Disconnect Modal -->\r\n<div class=\"custom-modal\" *ngIf=\"showDisconnectModal\">\r\n <div class=\"modal-content p-3\">\r\n <div class=\"contacts-header p-0 pb-2\">\r\n <h4 class=\"title mb-0\">Call Disconnected</h4>\r\n <div class=\"d-flex justify-content-between\">\r\n <span class=\"material-symbols-outlined dial-close-btn\" (click)=\"showDisconnectModal = false\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\" width=\"24px\"\r\n fill=\"#000000\">\r\n <path\r\n d=\"m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z\" />\r\n </svg>\r\n </span>\r\n </div>\r\n </div>\r\n\r\n <p class=\"mt-2\">\r\n You can end conference call or leave conference call.\r\n </p>\r\n\r\n <div class=\"button-group\">\r\n <button class=\"btn end-btn\" (click)=\"endConference()\">\r\n <span class=\"material-symbols-outlined mr-2\"> call_end </span>\r\n End All\r\n </button>\r\n\r\n <button class=\"btn end-btn\" (click)=\"leaveConference()\">\r\n <span class=\"material-symbols-outlined mr-2\"> call_end </span>\r\n Leave\r\n </button>\r\n </div>\r\n\r\n </div>\r\n</div>", styles: [".call-container{width:385px;height:646px!important;margin:auto;border-radius:20px;box-shadow:6px 6px 10px -1px #00000026,-5px -4px 10px -1px #00000026;display:flex;box-sizing:border-box;position:relative;justify-content:center;align-items:center;z-index:1000;flex-flow:column;overflow:hidden}.call-to-text{padding:6px 10px;border:1px solid #c2c2c2;border-radius:20px;font-size:13px}.collops{height:660px!important}.incoming-call-container{flex-flow:row!important}.active-call{width:385px!important}.call-animation{background:#fff;width:100px;height:100px;position:relative;margin:20px auto 0;border-radius:100%;border:solid 4px #fff;display:flex;align-items:center;justify-content:center}.call-animation:before{position:absolute;content:\"\";top:0;left:0;width:100%;height:100%;backface-visibility:hidden;border-radius:50%}.call-animation-play{animation:play 3s linear infinite}.call-info-wrapper{height:20px;overflow-y:auto;background:white;transition:height 1s}.open-collops{height:180px!important}.avatar-img{width:94px;height:94px;border-radius:100%}@keyframes play{0%{transform:scale(1)}15%{box-shadow:0 0 0 2px #fff6}25%{box-shadow:0 0 0 4px #fff6,0 0 0 8px #fff3}25%{box-shadow:0 0 0 8px #fff6,0 0 0 16px #fff3}50%{box-shadow:0 0 0 10px #fff6,0 0 0 20px #fff3}to{box-shadow:0 0 0 10px #fff6,0 0 0 20px #fff3;transform:scale(1.1);opacity:0}}.callerDetails{margin-top:8px;color:#fff;display:flex;flex-direction:column;align-items:center}.togglearrow-arrow{left:100%;background-color:#fff;width:25px;height:25px;text-align:center;cursor:pointer;border:1px solid #ccc;border-radius:50%;line-height:22px}.togglearrow-arrow.disabled{opacity:.3;cursor:not-allowed;pointer-events:none}.search-bar input{width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;outline:none;margin-bottom:10px}.togglearrow-arrow.disabled:hover{opacity:.3;cursor:not-allowed}.callerDetails h1{width:260px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin:12px 0 0;color:#fff;text-transform:capitalize;text-align:center}.callerDetails h4{margin:0;color:#fff}.tx-black,.title{color:#000!important}.callerDetails p{margin-top:-3px;margin-bottom:0;color:#fff}.call-sec-btn,.mic-btn{position:relative;box-sizing:border-box;border:1px solid #cccbcb;background-color:transparent;border-radius:25px;padding:12px;box-shadow:6px 6px 10px -1px #bebebe26,-5px -4px 10px -1px #d2d2d226;width:50px;height:50px}.mic-btn{padding:5px;width:37px;height:37px}.receive-btn{background-color:#28a745!important;color:#fff!important}.receive-btn span{color:#fff!important}.scroll-container{width:100%;overflow:hidden;white-space:nowrap;position:relative}.scroll-text{display:inline-block;padding-left:100%;animation:scroll-left 12s linear infinite;font-size:16px}@keyframes scroll-left{0%{transform:translate(0)}to{transform:translate(-100%)}}.call-sec-btn span{color:#cccbcb}.call-btn{width:60px;height:60px;background-color:#fff;border-radius:30px;box-sizing:border-box;border:2px solid white;margin:0 16px}.end-call-btn{background-color:#e14e4e}.end-call-btn span{color:#fff!important}.call-btn span{color:#234de8}.btn-container{display:flex;flex-wrap:wrap;padding:0 30px}.key-btn{width:50px;height:50px;background-color:transparent;text-align:center;box-sizing:border-box;margin:0 18px;font-size:22px;display:flex;flex-direction:column;justify-content:center;align-items:center;font-family:Lato,sans-serif;font-weight:900;font-style:normal;color:#d3d3d3;cursor:pointer;opacity:.8}.call-action-btns{text-align:center}#call-input{background-color:transparent;border:none;outline:none;text-align:center;color:#fff}.sendDigit{position:relative;text-align:center;width:80%;margin:auto;background-color:#ffffff1a;padding:2px 0;border-radius:3px}.input-clear-btn{position:absolute;right:6px;color:#fff;cursor:pointer}#minimize-btn-div{position:absolute;right:14px;top:12px;z-index:10}.minimize-btn{color:#fff;cursor:pointer}.wave-container{position:absolute;bottom:-4px;overflow:hidden;width:100%}.waves{width:660px;position:relative;margin-bottom:-7px;height:40px;min-height:40px}.held-call-banner{position:absolute;top:0;left:0;right:0;background:#1644f09c;z-index:2100;box-shadow:0 4px 12px #0000004d;border-radius:0 0 16px 16px;max-height:220px;overflow-y:auto}.held-call-content{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:6px 6px 0;padding-bottom:6px;border-bottom:1px dotted #4b4b4b}.held-info{display:flex;align-items:center;gap:10px;flex:1}.hold-icon{font-size:24px;color:#fbbf24}.swap-icon{font-size:24px}.held-caller{display:flex;flex-direction:column;gap:2px}.held-label{font-size:10px;color:#ffffffb3;text-transform:uppercase;letter-spacing:.5px}.held-name{font-size:14px;font-weight:600;color:#fff}.held-number{font-size:13px;font-weight:500;color:#fff}.held-actions{display:flex;gap:8px;align-items:center}.held-btn{padding:6px 16px;border-radius:20px;border:none;font-size:13px;font-weight:600;cursor:pointer;transition:transform .2s,box-shadow .2s}.held-btn:hover{transform:scale(1.05);box-shadow:0 4px 12px #0003}.swap-btn{background:#3b82f6;color:#fff}.merge-btn{background:#10b981;color:#fff}.h-77px{height:77px}.incoming-banners-container{width:100%;padding:5px 8px;height:100%;gap:8px;overflow-y:auto}.call-container-model{width:385px!important;height:646px!important;margin:auto 0 0 1px;border-radius:20px;box-shadow:6px 6px 10px -1px #00000026,-5px -4px 10px -1px #00000026;display:flex;box-sizing:border-box;position:relative;overflow:hidden;justify-content:center;align-items:center}.incoming-banner{top:0;left:0;width:100%;right:0;background:linear-gradient(135deg,#1e3a8a 0%,#3b82f6 100%);padding:12px 16px;z-index:2000;box-shadow:0 4px 12px #0003;border-radius:16px}.incoming-banner-content{display:flex;align-items:center;justify-content:space-between;gap:12px}.incoming-info{flex:1;display:flex;flex-direction:column;gap:4px}.incoming-label{font-size:11px;color:#fffc;text-transform:uppercase;letter-spacing:.5px}.incoming-caller{display:flex;flex-direction:column;gap:2px}.caller-name{font-size:15px;font-weight:600;color:#fff}.caller-number{font-size:13px;color:#ffffffe6}.incoming-actions{display:flex;gap:8px;align-items:center}.banner-btn{width:44px;height:44px;border-radius:50%;border:none;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:transform .2s}.banner-btn:hover{transform:scale(1.1)}.banner-btn .material-symbols-outlined{font-size:20px}.accept-btn{background:#10b981}.accept-btn .material-symbols-outlined{color:#fff}.reject-btn{background:#ef4444}.reject-btn .material-symbols-outlined{color:#fff}.contacts-panel{position:absolute;top:0;bottom:12px;width:340px;background:#ffffff;border-radius:16px;box-shadow:0 10px 25px #00000026;display:flex;flex-direction:column;overflow:hidden;height:40.4rem;left:24.1rem;z-index:1000000}.contacts-header{height:56px;display:flex;align-items:center;justify-content:space-between;padding:0 16px;border-bottom:1px solid #f0f0f0}.contacts-header .title{font-weight:600}.contacts-header .back,.contacts-header .search{color:#9aa0a6;cursor:pointer}.disabled{opacity:.5;pointer-events:none}.contacts-list{padding:8px 8px 12px;overflow-y:auto}.contact-item{display:flex;align-items:center;padding:10px 8px;border-radius:10px}.contact-item:hover{background:#f7f9fc}.contact-avatar{width:37px;height:37px;border-radius:50%;object-fit:cover;margin-right:12px}.contact-info{flex:1}.contact-name{font-weight:600;color:#111827}.contact-title{font-size:12px;color:#6b7280}.contact-call-btn{display:inline-flex;align-items:center;gap:6px;background:#234de8;color:#fff;border:none;border-radius:16px;padding:8px;cursor:pointer}.contact-add-btn{background-color:#2ecc71!important}.conference-hold-contact{display:inline-flex;align-items:center;gap:5px;background:#727070;color:#fff;border:none;border-radius:50%;padding:7px;cursor:pointer}.conference-hold-contact.on-hold{background:#28a745!important;color:#fff}.user-info-section{width:100%;height:100%;overflow-y:auto;overflow-x:hidden!important}.user-info-section::-webkit-scrollbar{display:none}.toggle-btn{cursor:pointer}.text-container{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;transition:all .3s ease}.text-container.expanded{-webkit-line-clamp:unset}.userName{font-family:FontAwesome}.subject-text{display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden}.conference-contact{display:inline-flex;align-items:center;gap:5px;background:#e14e4e;color:#fff;border:none;border-radius:50%;padding:7px;cursor:pointer}.organizer-label{padding:1px 5px;font-size:11px;border-radius:10px;border:1px solid #a0a0a0;margin-top:2px;background:#fcfcfc}.custom-modal{position:absolute;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.5);display:flex;justify-content:center;align-items:center;z-index:1000;border-radius:21px}.modal-content{background:#ffffff;padding:25px;border-radius:8px;width:350px;text-align:center}.title{margin-bottom:15px;color:#d9534f}.message{margin-bottom:20px}.button-group{display:flex;justify-content:space-between}.btn{padding:8px 15px;border:none;border-radius:5px;cursor:pointer;font-weight:500}.end-btn{background-color:#dc3545;color:#fff;display:flex;align-items:center;font-size:13px}.leave-btn{background-color:#007bff;color:#fff}.contact-call-btn .material-symbols-outlined{font-size:18px;color:#fff}.contact-call-btn .label{font-size:12px}.parallax>use{animation:move-forever 25s cubic-bezier(.55,.5,.45,.5) infinite}.parallax>use:nth-child(1){animation-delay:-2s;animation-duration:7s}.parallax>use:nth-child(2){animation-delay:-3s;animation-duration:10s}.parallax>use:nth-child(3){animation-delay:-4s;animation-duration:13s}.parallax>use:nth-child(4){animation-delay:-5s;animation-duration:20s}@keyframes move-forever{0%{transform:translate3d(-90px,0,0)}to{transform:translate3d(85px,0,0)}}.animated-margin{transition:margin-top .5s ease}app-incoming-call{position:absolute;top:0;left:0;width:100%;height:100%;background-color:transparent;z-index:1001}.min-call-container{width:320px;height:124px;border-radius:20px;box-shadow:6px 6px 10px -1px #00000026,-5px -4px 10px -1px #00000026;display:flex;flex-direction:column;box-sizing:border-box;position:relative;overflow:hidden;margin:auto;align-items:center;padding:12px 16px;color:#fff}.min-call-animation{background:#fff;width:48px;height:48px;position:relative;margin:0 12px 0 auto;border-radius:100%;border:solid 2px #fff}.min-avatar-img{width:46px;height:46px;border-radius:100%;position:absolute;left:0;top:0}.min-callerDetails{color:#fff;display:flex;flex-direction:column;align-items:flex-start}.name{width:170px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:20px;margin:0;color:#fff}.min-callerDetails p{margin:0;color:#fff}.min-btn-container{position:relative;display:flex;width:100%;justify-content:flex-start;align-items:center;margin-top:6px}.min-call-sec-btn{width:40px;height:40px;box-sizing:border-box;border:1px solid #cccbcb;background-color:transparent;border-radius:20px;display:flex;align-items:center;justify-content:center;margin-right:12px;box-shadow:6px 6px 10px -1px #bebebe26,-5px -4px 10px -1px #d2d2d226}.min-call-sec-btn span{color:#cccbcb}.min-call-btn{width:40px;height:40px;border-radius:20px;box-sizing:border-box;border:2px solid white;display:flex;align-items:center;justify-content:center}.fullscreen{position:absolute;right:18px;top:14px;color:#e8e8e8;font-size:18px;cursor:pointer}.btn-container{display:flex;flex-wrap:wrap;padding:0 24px}.dial-btn{width:40px;height:40px;background-color:transparent;text-align:center;box-sizing:border-box;margin:4px 25px;font-size:24px;display:flex;flex-direction:column;justify-content:center;align-items:center;font-family:Lato,sans-serif;font-weight:900;font-style:normal;color:#b5b5b5;cursor:pointer}.btn-albhabets{font-family:Lato,sans-serif;font-size:12px;font-weight:400}.min-timer{width:50px;font-size:18px;margin-right:10px;border-radius:4px;height:35px;display:flex;align-items:center}.record-action-btns{display:flex;flex-direction:column;align-items:center;margin-top:35px}.record-btn-container{position:relative}.record-btn{border:none;border-radius:50%;width:50px;height:50px;display:flex;align-items:center;justify-content:center;cursor:pointer;margin:0 5px;position:relative;overflow:hidden}.record-btn.start-stop .recording-icon{width:50%;height:50%;border-radius:50%;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}.record-btn.start-stop.recording .recording-icon{background-color:#000}.record-btn.start-stop.recording{border:3px solid #000}.record-btn.start-stop.stopped .recording-icon{background-color:red;border:3px solid #ff0000;border-radius:50%;position:absolute}.record-btn.start-stop.stopped{border:3px solid #ff0000}.record-btn.start-stop.stopped .recording-icon{width:40%;height:40%;border-radius:0;background-color:red}.pause-resume-btns{display:flex;flex-direction:column;align-items:center;margin-top:10px}.record-btn.pause-resume{border:none;border-radius:50%;width:50px;height:50px;background:white;display:flex;align-items:center;justify-content:center;margin:5px 0}.record-btn.pause-resume .material-symbols-outlined{font-size:20px;color:#000}.timer-display{font-size:1.2em;margin-top:10px;color:#000}.w-40{width:40%}.w-60{width:60%}.callToNum{color:#fff;font-weight:400;text-align:center}.callToNum span{font-weight:600}.conference-call-view{display:flex;flex-direction:column;align-items:center;justify-content:flex-start;width:100%;padding:12px 16px 35px;color:#fff;height:100%}.conf-heading{display:flex;align-items:center;gap:8px;margin-top:8px}.conf-icon{color:#4579aa;font-size:32px;width:50px;height:50px;border:1px solid gray;border-radius:50%;display:flex;align-items:center;justify-content:center;background:#e1e1e1}.conf-title{font-weight:600;font-size:20px}.conf-name{margin-top:10px;font-size:17px;font-weight:600;text-align:center}.conf-timer{margin-top:4px;font-size:12px;opacity:.9}.conf-record{margin-top:14px}.record-stop-btn{width:44px;height:44px;border-radius:50%;border:none;background:#fff;display:flex;align-items:center;justify-content:center}.record-stop-btn .material-symbols-outlined{color:#e14e4e;font-size:28px}.conf-remove{margin-top:8px}.remove-btn{background:#ff0000!important;color:#fff;border:none;border-radius:6px;padding:6px 12px;font-size:12px;width:82px!important;height:auto}.conf-actions{margin-top:14px;display:flex;align-items:center;justify-content:center;gap:18px}.circle-btn{width:56px;height:56px;border-radius:50%;border:none;background:#000;display:flex;align-items:center;justify-content:center}.circle-btn .material-symbols-outlined{color:#fff;font-size:24px}.circle-btn.active{opacity:.85}.conf-end{margin-top:16px}.circle-btn.danger{background:#e14e4e}.circle-btn.danger .material-symbols-outlined{color:#fff}\n"], dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i6.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
|
|
3588
3223
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CallProgressComponent, decorators: [{
|
|
3589
3224
|
type: Component,
|
|
3590
|
-
args: [{ selector: 'lib-call-progress', template: "<div class=\"d-flex\">\r\n <div class=\"call-container\" *ngIf=\"!isMinimised && currentCallList?.length\"\r\n [ngClass]=\"{'collops': isCollops, 'incoming-call-container': isClickExpand, 'contacts-open': showContactsPanel }\">\r\n <!-- <ng-container *ngIf=\"!incomingCallDiv || isConcurrentIncoming || true\"> -->\r\n <!-- All type Call Hold list -->\r\n <div class=\"held-call-banner\"\r\n *ngIf=\"currentCallList.length > 1 && !!currentCall && ((isConferenceCallHold || isConference) || !isConference)\">\r\n <ng-container *ngFor=\"let conf of conferenceCallList\">\r\n <div class=\"held-call-content\" *ngIf=\"conf?.isHold\">\r\n <div class=\"held-info\">\r\n <span class=\"material-symbols-outlined hold-icon\">pause_circle</span>\r\n <div class=\"held-caller\">\r\n <span class=\"held-label\">Hold</span>\r\n <span class=\"held-name\">Conference Call</span>\r\n </div>\r\n </div>\r\n <div class=\"held-actions\">\r\n <button class=\"conference-hold-contact\" [ngClass]=\"{ 'on-hold': conf?.isHold }\" (click)=\"swapCalls(conf,true)\">\r\n <span class=\"material-symbols-outlined\" title=\"{{'Hold'}}\"> phone_paused </span>\r\n </button>\r\n <button class=\"conference-contact\" (click)=\"endCall(true)\">\r\n <span class=\"material-symbols-outlined\" title=\"Call End\"> call_end </span>\r\n </button>\r\n <div class=\"togglearrow-arrow me-2\" id=\"togglearrow\"\r\n (click)=\"toggleContactsPanel(conf)\">\r\n <i class=\"fa fa-angle-right\"></i>\r\n </div>\r\n </div>\r\n </div>\r\n </ng-container>\r\n <ng-container *ngFor=\"let heldCall of currentCallList\">\r\n <div class=\"held-call-content\" *ngIf=\"heldCall?.isHold && !heldCall?.isConference\">\r\n <div class=\"held-info\">\r\n <span class=\"material-symbols-outlined hold-icon\">pause_circle</span>\r\n <div class=\"held-caller\">\r\n <span class=\"held-label\">Hold</span>\r\n <span class=\"held-name\">{{heldCall?.name || 'Unknown number'}}</span>\r\n <span class=\"held-number\">{{heldCall?.phone || ''}}</span>\r\n </div>\r\n </div>\r\n <div class=\"held-actions\">\r\n <button class=\"conference-hold-contact\" [ngClass]=\"{ 'on-hold': heldCall?.isHold }\" (click)=\"swapCalls(heldCall)\">\r\n <span class=\"material-symbols-outlined\" title=\"{{heldCall?.isHold? 'Resume':'Hold'}}\"> phone_paused </span>\r\n </button>\r\n <button class=\"conference-contact\" (click)=\"onEndCall(heldCall)\">\r\n <span class=\"material-symbols-outlined\" title=\"Call End\"> call_end </span>\r\n </button>\r\n <div class=\"togglearrow-arrow me-2\" id=\"togglearrow\" *ngIf=\"heldCall?.isIncomingCall\"\r\n (click)=\"onClickExpand(heldCall)\" [ngClass]=\"{'disabled': !heldCall?.businessNumber}\">\r\n <i class=\"fa fa-angle-right\"></i>\r\n </div>\r\n <!-- <button class=\"held-btn swap-btn\" (click)=\"swapCalls(heldCall)\" title=\"Swap calls\">\r\n <span class=\"material-symbols-outlined swap-icon\">swap_vert</span>\r\n </button> -->\r\n </div>\r\n </div>\r\n <div class=\"held-call-content\" *ngIf=\"heldCall?.isIncomingCall && !heldCall?.isAcceptCall\">\r\n <div class=\"held-info\">\r\n <span class=\"material-symbols-outlined hold-icon\">phone_callback</span>\r\n <div class=\"held-caller\">\r\n <span class=\"held-label\">Incoming Call</span>\r\n <span class=\"held-name\">{{heldCall?.name || 'Unknown number'}}</span>\r\n <span class=\"held-number\">{{heldCall?.phone || ''}}</span>\r\n </div>\r\n </div>\r\n <div class=\"held-actions\">\r\n <button class=\"banner-btn receive-btn\" *ngIf=\"!heldCall?.isAcceptCall\">\r\n <span class=\"material-symbols-outlined\" (click)=\"add(heldCall)\"> call </span>\r\n </button>\r\n <button class=\"call-btn-wrapper banner-btn reject-btn\">\r\n <span class=\"material-symbols-outlined\" (click)=\"onEndCall(heldCall)\"> call_end\r\n </span>\r\n </button>\r\n <div class=\"togglearrow-arrow me-2\" id=\"togglearrow\"\r\n (click)=\"onClickExpand(heldCall)\" [ngClass]=\"{'disabled': !heldCall?.businessNumber}\">\r\n <i class=\"fa fa-angle-right\"></i>\r\n </div>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n <!-- Compact banners for concurrent incoming (one per call) -->\r\n <!-- <ng-container *ngIf=\"currentCallList.length > 1 && !currentCall?.id\">\r\n <div class=\"incoming-banners-container\" *ngIf=\"!isConference && currentCallList.length > 1\">\r\n <div class=\"\">\r\n <ng-container *ngFor=\"let inc of currentCallList; let i = index\">\r\n <div class=\"incoming-banner\" *ngIf=\"inc?.isIncomingCall && !inc?.isAcceptCall\"\r\n [ngStyle]=\"{ top: ((isCallOnHold && heldCall) ? 64 : 0) + (i * 70) + 'px' }\">\r\n <div class=\"incoming-banner-content\">\r\n <div class=\"incoming-info\">\r\n <span class=\"incom ing-label\">Incoming call</span>\r\n <div class=\"incoming-caller\">\r\n <span class=\"caller-name\">{{ inc?.userInfo?.c2cInformation?.name ||\r\n inc?.customParameters?.get('name') || '-' }}</span>\r\n <span class=\"caller-number\">{{ inc?.userInfo?.c2cInformation?.number ||\r\n inc?.parameters?.From || '' }}</span>\r\n </div>\r\n </div>\r\n <div class=\"incoming-actions\">\r\n <button class=\"banner-btn accept-btn\" (click)=\"add(inc)\">\r\n <span class=\"material-symbols-outlined\">call</span>\r\n </button>\r\n <button class=\"banner-btn reject-btn\" (click)=\"onEndCall(inc)\">\r\n <span class=\"material-symbols-outlined\">call_end</span>\r\n </button>\r\n <div class=\"togglearrow-arrow me-2\" id=\"togglearrow\"\r\n (click)=\"onClickExpand(inc)\" [ngClass]=\"{'disabled': !inc?.businessNumber}\">\r\n <i class=\"fa fa-angle-right\"></i>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </ng-container> -->\r\n\r\n <!-- For single incoming call -->\r\n <div class=\"h-100 py-5\" style=\"display: flex; flex-direction: column;\"\r\n *ngIf=\"currentCallList.length === 1 && currentCallList[0]?.isIncomingCall && !currentCallList[0]?.isAcceptCall \">\r\n <div class=\"callToNum\">Incoming call on <br /><span>{{currentCallList[0]?.to || 'Unknown\r\n Number'}}</span>\r\n </div>\r\n <div class=\"call-animation\" [ngClass]=\"{'call-animation-play': showRingAnimation}\">\r\n <img class=\"avatar-img\" [src]=\"currentCallList[0]?.img\" alt=\"\" width=\"120\" />\r\n </div>\r\n <div class=\"callerDetails\">\r\n <h1>{{ currentCallList[0]?.name ? currentCallList[0]?.name : currentCallList[0]?.phone || 'Unknown Number' }}</h1>\r\n <p *ngIf=\"!!currentCallList[0]?.name\">{{ currentCallList[0]?.phone }}</p>\r\n </div>\r\n\r\n <div class=\"call-action-btns mt-auto\">\r\n <button class=\"call-btn receive-btn\" *ngIf=\"!newIncomingCallsList[0]?.isCallConnected\" [disabled]=\"isIncomingCallBtnDisable\">\r\n <span class=\"material-symbols-outlined\" (click)=\"add(currentCallList[0])\"> call </span>\r\n </button>\r\n <button class=\"call-btn reject-btn\">\r\n <span class=\"material-symbols-outlined\" (click)=\"onEndCall(currentCallList[0])\"> call_end\r\n </span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- For single active call --> \r\n <div *ngIf=\"(!isConference || isConferenceCallHold) && (!!currentCall?.id && !currentCall?.isConference)\"\r\n [ngStyle]=\"{'display': 'flex', 'flex-direction': 'column', 'position': 'relative'}\" class=\"active-call\">\r\n\r\n <div class=\"call-animation\" [ngClass]=\"{'call-animation-play': showRingAnimation}\">\r\n <img class=\"avatar-img\" [src]=\"currentCall?.img\" alt=\"\" width=\"120\" />\r\n </div>\r\n <div class=\"callerDetails\">\r\n <h1 [ngStyle]=\"{'margin-top': showKeypad ? '0': '8px'}\">{{currentCall?.name || 'Unknown number'}}\r\n </h1>\r\n <p>{{currentCall?.phone }}</p>\r\n <h4 style=\"margin-top: 4px\">{{currentCall?.time || timer}}</h4>\r\n </div>\r\n\r\n <div class=\"record-action-btns\" *ngIf=\"!showKeypad\"\r\n [ngStyle]=\"{'margin-top': showKeypad ? '0': '20px'}\">\r\n <div class=\"record-btn-container\">\r\n <button class=\"record-btn start-stop\" *ngIf=\"!isRecording\"\r\n [ngClass]=\"{'recording': isRecording, 'stopped': !isRecording}\" (click)=\"toggleRecording()\"\r\n [title]=\"isRecording ? 'Stop Recording' : 'Start Recording'\"\r\n [disabled]=\"!currentCall?.isAcceptCall\">\r\n <span class=\"recording-icon\"></span>\r\n </button>\r\n <div class=\"pause-resume-btns\">\r\n <button class=\"record-btn pause-resume\" *ngIf=\"isRecording && !isPaused\"\r\n (click)=\"pauseRecording()\">\r\n <span class=\"material-symbols-outlined\"> pause </span>\r\n </button>\r\n <button class=\"record-btn pause-resume\" *ngIf=\"isPaused\" (click)=\"resumeRecording()\">\r\n <span class=\"material-symbols-outlined\"> play_arrow </span>\r\n </button>\r\n </div>\r\n </div>\r\n <div *ngIf=\"isRecording\" class=\"timer-display\">\r\n {{ getFormattedTime() }}\r\n </div>\r\n </div>\r\n <div *ngIf=\"showKeypad\" class=\"sendDigit\">\r\n <input type=\"text\" name=\"call-inputs\" id=\"call-input\" [(ngModel)]=\"callInput\"\r\n (keyup)=\"onCallInputEnter($event)\">\r\n <span class=\"material-symbols-outlined input-clear-btn\" *ngIf=\"callInput\"\r\n (click)=\"clearInputs()\">close_small</span>\r\n </div>\r\n <div class=\"btn-container justify-content-center\" *ngIf=\"showKeypad\">\r\n <div class=\"key-btn\" *ngFor=\"let key of keypadVal\" (click)=\"onCallInputs(key.num)\">\r\n {{key.num}}\r\n <span class=\"btn-albhabets\">{{key.text ? key.text : ' '}}</span>\r\n </div>\r\n </div>\r\n\r\n <div class=\"call-action-btns\" [ngStyle]=\"{'margin-top': showKeypad ? '0': '723x'}\">\r\n <div class=\"mb-3\" *ngIf=\"!incomingCallDiv || isConcurrentIncoming\">\r\n <button class=\"held-btn merge-btn\" (click)=\"mergeCalls()\" title=\"Merge calls\"\r\n [disabled]=\"isMergeCallAllowed() || currentCallList.length < 2\">\r\n <span>Merge</span>\r\n </button>\r\n </div>\r\n <div class=\"flex align-items-center justify-content-evenly mb-3\">\r\n <button class=\"call-sec-btn mr-3\" [disabled]=\"!currentCall?.isAcceptCall\"\r\n (click)=\"toggleMute()\">\r\n <span class=\"material-symbols-outlined\" *ngIf=\"isMute\"> mic_off </span>\r\n <span class=\"material-symbols-outlined\" *ngIf=\"!isMute\"> mic </span>\r\n\r\n </button>\r\n <button class=\"call-sec-btn mr-3\" [disabled]=\"!currentCall?.isAcceptCall\">\r\n <span class=\"material-symbols-outlined\" (click)=\"toggleKeypad()\"> transition_dissolve\r\n </span>\r\n </button>\r\n <button class=\"call-sec-btn\" [disabled]=\"!currentCall?.isAcceptCall\"\r\n (click)=\"toggleContactsPanel(currentCall)\">\r\n <span class=\"material-symbols-outlined\"> groups_2 </span>\r\n </button>\r\n </div>\r\n\r\n <div>\r\n <button class=\"call-btn end-call-btn\" [disabled]=\"!currentCall?.isAcceptCall\"\r\n (click)=\"endCall()\">\r\n <span class=\"material-symbols-outlined\"> call_end </span>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- conference call view -->\r\n <div class=\"conference-call-view\" *ngIf=\"isConference && currentCall?.isConference\">\r\n <div class=\"conf-heading\">\r\n <span class=\"conf-icon material-symbols-outlined\"> groups </span>\r\n <span class=\"conf-title\">Conference Call</span>\r\n </div>\r\n\r\n <div class=\"scroll-container\">\r\n <div class=\"scroll-text conf-name\">\r\n <ng-container *ngFor=\"let call of currentCallList; let i = index\">\r\n <ng-container *ngIf=\"call?.isConference\">\r\n <span *ngIf=\"i != 0\">&</span>\r\n {{call?.name ? call?.name : call?.phone || 'Unknown number'}}\r\n </ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n <div class=\"conf-timer\">{{ timer }}</div>\r\n\r\n <div class=\"record-action-btns mt-auto\" *ngIf=\"!showKeypad\"\r\n [ngStyle]=\"{'margin-top': showKeypad ? '0': '20px'}\">\r\n <div class=\"record-btn-container\">\r\n <button class=\"record-btn start-stop\" *ngIf=\"!isRecording\"\r\n [ngClass]=\"{'recording': isRecording, 'stopped': !isRecording}\" (click)=\"toggleRecording()\"\r\n [title]=\"isRecording ? 'Stop Recording' : 'Start Recording'\">\r\n <span class=\"recording-icon\"></span>\r\n </button>\r\n <div class=\"pause-resume-btns\">\r\n <button class=\"record-btn pause-resume\" *ngIf=\"isRecording && !isPaused\"\r\n (click)=\"pauseRecording()\">\r\n <span class=\"material-symbols-outlined\"> pause </span>\r\n </button>\r\n <button class=\"record-btn pause-resume\" *ngIf=\"isPaused\" (click)=\"resumeRecording()\">\r\n <span class=\"material-symbols-outlined\"> play_arrow </span>\r\n </button>\r\n </div>\r\n </div>\r\n <div *ngIf=\"isRecording\" class=\"timer-display\">\r\n {{ getFormattedTime() }}\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"showKeypad\" class=\"sendDigit mt-2\">\r\n <input type=\"text\" name=\"call-inputs\" id=\"call-input\" [(ngModel)]=\"callInput\"\r\n (keyup)=\"onCallInputEnter($event)\">\r\n <span class=\"material-symbols-outlined input-clear-btn\" *ngIf=\"callInput\"\r\n (click)=\"clearInputs()\">close_small</span>\r\n </div>\r\n <div class=\"btn-container justify-content-center\" *ngIf=\"showKeypad\">\r\n <div class=\"key-btn\" *ngFor=\"let key of keypadVal\" (click)=\"onCallInputs(key.num)\">\r\n {{key.num}}\r\n <span class=\"btn-albhabets\">{{key.text ? key.text : ' '}}</span>\r\n </div>\r\n </div>\r\n\r\n <div class=\"conf-actions\">\r\n <button class=\"circle-btn\" [ngClass]=\"{'active': isMute}\" (click)=\"toggleMute(true)\">\r\n <span class=\"material-symbols-outlined\"> {{ isMute ? 'mic_off' : 'mic' }} </span>\r\n </button>\r\n <button class=\"circle-btn\" (click)=\"toggleKeypad()\">\r\n <span class=\"material-symbols-outlined\"> transition_dissolve </span>\r\n </button>\r\n <button class=\"circle-btn\" (click)=\"toggleContactsPanel(currentCall)\">\r\n <span class=\"material-symbols-outlined\"> groups_2 </span>\r\n </button>\r\n </div>\r\n\r\n <div class=\"conf-end\">\r\n <button class=\"circle-btn danger\" (click)=\"endCall(true)\">\r\n <span class=\"material-symbols-outlined\"> call_end </span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"wave-container\">\r\n <svg class=\"waves\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\r\n viewBox=\"0 24 150 28\" preserveAspectRatio=\"none\" shape-rendering=\"auto\">\r\n <defs>\r\n <path id=\"gentle-wave\"\r\n d=\"M-160 44c30 0 58-18 88-18s 58 18 88 18 58-18 88-18 58 18 88 18 v44h-352z\" />\r\n </defs>\r\n <g class=\"parallax\">\r\n <use xlink:href=\"#gentle-wave\" x=\"48\" y=\"0\" fill=\"rgba(255,255,255,0.7)\" />\r\n <use xlink:href=\"#gentle-wave\" x=\"48\" y=\"3\" fill=\"rgba(255,255,255,0.5)\" />\r\n <use xlink:href=\"#gentle-wave\" x=\"48\" y=\"7\" fill=\"#fff\" />\r\n </g>\r\n </svg>\r\n </div>\r\n <!-- </ng-container> -->\r\n </div>\r\n\r\n <!-- Incoming call user details shown in model -->\r\n <div class=\"call-container-model p-3 text-white model-content call-container\" *ngIf=\"isClickExpand\">\r\n <div class=\"mb-2 user-info-section\" >\r\n <div class=\"text-center my-3\">\r\n <h3 class=\"text-white\">C2C -POINT {{selectedUserInfo?.pointName}}</h3>\r\n </div>\r\n <div class=\"mb-3\">\r\n <h5 class=\"text-white mb-1\">Name:</h5>\r\n <h4 class=\"text-white userName\">{{selectedUserInfo?.name}}</h4>\r\n </div>\r\n <div class=\"f-13\">\r\n <div class=\"row mb-3\">\r\n <div class=\"col-6 mb-2\">\r\n <div class=\"mb-1\">Number:</div>\r\n <div class=\"\">{{selectedUserInfo?.number}}</div>\r\n </div>\r\n <div class=\"col-6 mb-2\">\r\n <div class=\"mb-1\">Extension:</div>\r\n <div class=\"ml-2\">{{selectedUserInfo?.extension}}</div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"row mb-3\">\r\n <div class=\"col-12 mb-2\">\r\n <div class=\"me-2\">Email: </div>\r\n <div>{{selectedUserInfo?.email}}</div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"row mb-3\">\r\n <div class=\"col-12 mb-2\">\r\n <div class=\"me-2\">Subject:</div>\r\n <div class=\"ml-2 subject-text\" title=\"{{selectedUserInfo?.subject}}\">{{selectedUserInfo?.subject}}</div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"row mb-3\">\r\n <div class=\"col-12 mb-2\">\r\n <div class=\"me-2 mb-1\">Image:</div>\r\n <div class=\"text-ellipsis\">\r\n <ng-container *ngIf=\"selectedUserInfo?.image && selectedUserInfo?.image !== '-'; else noImage\">\r\n <img src=\"{{selectedUserInfo?.image}}\" alt=\"\" width=\"150\" class=\"ml-2\"/>\r\n </ng-container>\r\n <ng-template #noImage>\r\n <span class=\"ml-2\">No Image Available</span>\r\n </ng-template>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\" mb-4\">\r\n <div class=\"\">\r\n <div class=\"mb-1\">Message:</div>\r\n <div>\r\n <div class=\"text-container\" [class.expanded]=\"isExpanded\">{{selectedUserInfo?.message}}</div>\r\n <small class=\"toggle-btn\" *ngIf=\"showButton\" (click)=\"toggleText()\">{{ isExpanded ? 'See less' : 'See more' }}</small>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"row mb-3\">\r\n <div class=\"col-6 mb-2\">\r\n <div class=\"mb-1\">Point Name:</div>\r\n <div class=\"\">{{selectedUserInfo?.pointName}}</div>\r\n </div>\r\n <div class=\"col-6 mb-2\">\r\n <div class=\"mb-1\">Source Name:</div>\r\n <div class=\"\">{{selectedUserInfo?.sourceName}}</div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- contact list panel -->\r\n <div class=\"contacts-panel\" *ngIf=\"showContactsPanel\">\r\n <div class=\"contacts-header\">\r\n <div class=\"title\">Participent</div>\r\n <div class=\"d-flex justify-content-between\">\r\n <p></p>\r\n <span class=\"material-symbols-outlined dial-close-btn\" (click)=\"toggleContactsPanel({}, true)\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\" width=\"24px\" fill=\"#000000\"><path d=\"m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z\"/></svg>\r\n </span>\r\n </div>\r\n </div>\r\n\r\n <!-- SEARCH INPUT (visible when isSearchVisible = true) -->\r\n <div class=\"search-bar p-3\">\r\n <input type=\"text\" placeholder=\"Search...\" [(ngModel)]=\"searchText\" (input)=\"applyFilter()\" />\r\n <ng-container *ngFor=\"let c of filteredList\">\r\n <div class=\"contact-item\" *ngIf=\"isDirectCallOptionShow && searchText\">\r\n <img class=\"contact-avatar\" [src]=\"c?.img || 'assets/images/user.jpg'\" alt=\"\" />\r\n <div class=\"contact-info\">\r\n <div class=\"contact-name\">{{c?.firstName}} {{c?.middleName}} {{c?.lastName}}</div>\r\n <div class=\"contact-title\">{{ (c?.numbersList && c?.numbersList[0]?.number)}}</div>\r\n </div>\r\n <button class=\"contact-call-btn contact-add-btn mr-2\" (click)=\"callContact(c)\" *ngIf=\"!c?.IsConnected\" title=\"Add to conference call\">\r\n <span class=\"material-symbols-outlined\"> add </span>\r\n </button>\r\n <button class=\"contact-call-btn\" (click)=\"CallToUnsavedNumber(c?.numbersList[0]?.number, true)\" *ngIf=\"!c?.IsConnected\" title=\"New Call\">\r\n <span class=\"material-symbols-outlined\"> call </span>\r\n </button>\r\n </div>\r\n </ng-container>\r\n <ng-container *ngIf=\"!filteredList.length\">\r\n <div class=\"contact-item\" *ngIf=\"searchText\">\r\n <img class=\"contact-avatar\" [src]=\"'assets/images/user.jpg'\" alt=\"\" />\r\n <div class=\"contact-info\">\r\n <div class=\"contact-title\">{{ searchText }}</div>\r\n </div>\r\n <button class=\"contact-call-btn contact-add-btn mr-2\" (click)=\"callContact(searchText, true)\" title=\"Add to conference call\">\r\n <span class=\"material-symbols-outlined\"> add </span>\r\n </button>\r\n <button class=\"contact-call-btn\" (click)=\"CallToUnsavedNumber(searchText, true)\" title=\"New Call\">\r\n <span class=\"material-symbols-outlined\"> call </span>\r\n </button>\r\n </div>\r\n </ng-container>\r\n </div>\r\n <div class=\"contacts-list\">\r\n <div class=\"px-2\">\r\n <h5 class=\"mb-0 title\">In This Call</h5>\r\n </div>\r\n <hr class=\"mb-2 mt-1\">\r\n <div class=\"contact-item\" *ngFor=\"let c of filteredParticipentList\">\r\n <ng-container *ngIf=\"c?.to == 'client' else participentInfo\">\r\n <img class=\"contact-avatar\" [src]=\"c?.fromImage || 'assets/images/user.jpg'\" alt=\"\" />\r\n <div class=\"contact-info\">\r\n <div class=\"contact-name\">You\r\n </div>\r\n <div class=\"contact-title\">{{ c?.from }}</div>\r\n </div>\r\n <button class=\"mic-btn mr-2\" [disabled]=\"c?.hold\"\r\n (click)=\"onMuteUser(c)\">\r\n <span class=\"material-symbols-outlined\" *ngIf=\"c?.isMute\"> mic_off </span>\r\n <span class=\"material-symbols-outlined\" *ngIf=\"!c?.isMute\"> mic </span>\r\n </button>\r\n <button class=\"conference-hold-contact mr-2\" [ngClass]=\"{ 'on-hold': c?.hold }\" (click)=\"onHoldCall(c)\">\r\n <span class=\"material-symbols-outlined\" [title]=\"!c?.hold ? 'Hold' : 'Resume'\"> phone_paused </span>\r\n </button>\r\n <button class=\"conference-contact\" (click)=\"onEndCall(c, false, true)\">\r\n <span class=\"material-symbols-outlined\" title=\"Call End\"> call_end </span>\r\n </button>\r\n </ng-container>\r\n <ng-template #participentInfo>\r\n <img class=\"contact-avatar\" [src]=\"c?.direction == 'outgoing-call' ? c?.toImage : c?.fromImage || 'assets/images/user.jpg'\" alt=\"\" />\r\n <div class=\"contact-info\">\r\n <div class=\"contact-name\">{{c?.direction == 'outgoing-call' ? c?.toName || 'Unknown' : c?.fromName || 'Unknown'}}\r\n </div>\r\n <div class=\"contact-title\">{{ c?.direction == 'outgoing-call' ? c?.to || 'Unknown' : c?.from ||\r\n 'Unknown'}}</div>\r\n <div class=\"d-flex\" *ngIf=\"c?.from == hostnumber?.from\">\r\n <span class=\"organizer-label\">Organizer</span>\r\n </div>\r\n </div>\r\n <button class=\"mic-btn mr-2\" [disabled]=\"c?.hold\"\r\n (click)=\"onMuteUser(c)\">\r\n <span class=\"material-symbols-outlined\" *ngIf=\"c?.isMute\"> mic_off </span>\r\n <span class=\"material-symbols-outlined\" *ngIf=\"!c?.isMute\"> mic </span>\r\n </button>\r\n <button class=\"conference-hold-contact mr-2\" [ngClass]=\"{ 'on-hold': c?.hold }\" (click)=\"onHoldCall(c)\">\r\n <span class=\"material-symbols-outlined\" [title]=\"!c?.hold ? 'Hold' : 'Resume'\"> phone_paused </span>\r\n </button>\r\n <button class=\"conference-contact\" (click)=\"onEndCall(c, false, true)\">\r\n <span class=\"material-symbols-outlined\" title=\"Call End\"> call_end </span>\r\n </button>\r\n </ng-template>\r\n </div>\r\n <hr class=\"m-2\">\r\n <div class=\"mt-3 px-2\">\r\n <h5 class=\"mb-0 title\">Participent added to the call</h5>\r\n </div>\r\n <hr class=\"mb-2 mt-1\"> \r\n <ng-container *ngFor=\"let c of filteredList\">\r\n <div class=\"contact-item\" *ngIf=\"!c?.IsConnected && false\">\r\n <img class=\"contact-avatar\" [src]=\"c?.img ? c?.img : 'assets/images/user.jpg'\" alt=\"\" />\r\n <div class=\"contact-info\">\r\n <div class=\"contact-name\">{{c?.firstName}} {{c?.middleName}} {{c?.lastName}}</div>\r\n <div class=\"contact-title\">{{ (c?.numbersList && c?.numbersList[0]?.number)}}</div>\r\n </div>\r\n <button class=\"contact-call-btn\" (click)=\"callContact(c)\" *ngIf=\"!c?.IsConnected\">\r\n <span class=\"material-symbols-outlined\"> call </span>\r\n <span class=\"label\">Call</span>\r\n </button>\r\n <button class=\"conference-hold-contact mr-2\" [ngClass]=\"{ 'on-hold': c?.hold }\" (click)=\"onHoldCall(c)\" *ngIf=\"c?.IsConnected\">\r\n <span class=\"material-symbols-outlined\" title=\"Hold\"> phone_paused </span>\r\n </button>\r\n <button class=\"conference-contact\" (click)=\"onEndCall(c, false, true)\" *ngIf=\"c?.IsConnected\">\r\n <span class=\"material-symbols-outlined\" title=\"Call End\"> call_end </span>\r\n </button>\r\n </div>\r\n </ng-container>\r\n <ng-container *ngFor=\"let c of leftParticipent[currentCall?.conferenceId]\">\r\n <div class=\"contact-item\">\r\n <img class=\"contact-avatar\" [src]=\"c.direction == 'outgoing-call' && c?.toImage ? c?.toImage : c?.fromImage || 'assets/images/user.jpg'\" alt=\"\" />\r\n <div class=\"contact-info\">\r\n <div class=\"contact-name\">{{c.direction == 'outgoing-call' ? c?.toName : c?.fromName || 'Unknown number'}}</div>\r\n <div class=\"contact-title\">{{c.direction == 'outgoing-call' ? c?.to : c?.from}}</div>\r\n </div>\r\n <button class=\"contact-call-btn contact-add-btn \" (click)=\"CallToUnsavedNumber(c.direction == 'outgoing-call' ? c?.to : c?.from)\" >\r\n <span class=\"material-symbols-outlined\"> add </span>\r\n <span class=\"label\">Add</span>\r\n </button>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div class=\"min-call-container\" *ngIf=\"isMinimised\">\r\n <span class=\"material-symbols-outlined fullscreen\" (click)=\"maximiseDialpad()\"> open_in_full </span>\r\n <div style=\"display: flex; width: 100%\">\r\n <div>\r\n <div class=\"min-call-animation\" id=\"call-avatar\">\r\n <img class=\"min-avatar-img\" [src]=\"callData.img\" alt=\"\" />\r\n </div>\r\n </div>\r\n <div>\r\n <div class=\"min-callerDetails\">\r\n <div class=\"name\">\r\n {{callData.name}}\r\n </div>\r\n <p style=\"margin: 0\">{{callData.displayNum ? callData.displayNum : callData.phone }}</p>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"min-btn-container\">\r\n <div class=\"min-timer\">{{timer}}</div>\r\n <button class=\"min-call-sec-btn\" (click)=\"toggleMute()\" [disabled]=\"disbaleEndCallBtn\">\r\n <span class=\"material-symbols-outlined\" *ngIf=\"isMute\"> mic_off </span>\r\n <span class=\"material-symbols-outlined\" *ngIf=\"!isMute\"> mic </span>\r\n </button>\r\n <button class=\"min-call-btn end-call-btn\" [disabled]=\"disbaleEndCallBtn\" (click)=\"endCall()\">\r\n <span class=\"material-symbols-outlined\"> call_end </span>\r\n </button>\r\n </div>\r\n</div>", styles: [".call-container{width:385px;height:646px!important;margin:auto;border-radius:20px;box-shadow:6px 6px 10px -1px #00000026,-5px -4px 10px -1px #00000026;display:flex;box-sizing:border-box;position:relative;justify-content:center;align-items:center;z-index:1000;flex-flow:column;overflow:hidden}.call-to-text{padding:6px 10px;border:1px solid #c2c2c2;border-radius:20px;font-size:13px}.collops{height:660px!important}.incoming-call-container{flex-flow:row!important}.active-call{width:385px!important}.call-animation{background:#fff;width:100px;height:100px;position:relative;margin:20px auto 0;border-radius:100%;border:solid 4px #fff;display:flex;align-items:center;justify-content:center}.call-animation:before{position:absolute;content:\"\";top:0;left:0;width:100%;height:100%;backface-visibility:hidden;border-radius:50%}.call-animation-play{animation:play 3s linear infinite}.call-info-wrapper{height:20px;overflow-y:auto;background:white;transition:height 1s}.open-collops{height:180px!important}.avatar-img{width:94px;height:94px;border-radius:100%}@keyframes play{0%{transform:scale(1)}15%{box-shadow:0 0 0 2px #fff6}25%{box-shadow:0 0 0 4px #fff6,0 0 0 8px #fff3}25%{box-shadow:0 0 0 8px #fff6,0 0 0 16px #fff3}50%{box-shadow:0 0 0 10px #fff6,0 0 0 20px #fff3}to{box-shadow:0 0 0 10px #fff6,0 0 0 20px #fff3;transform:scale(1.1);opacity:0}}.callerDetails{margin-top:8px;color:#fff;display:flex;flex-direction:column;align-items:center}.togglearrow-arrow{left:100%;background-color:#fff;width:25px;height:25px;text-align:center;cursor:pointer;border:1px solid #ccc;border-radius:50%;line-height:22px}.togglearrow-arrow.disabled{opacity:.3;cursor:not-allowed;pointer-events:none}.search-bar input{width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;outline:none;margin-bottom:10px}.togglearrow-arrow.disabled:hover{opacity:.3;cursor:not-allowed}.callerDetails h1{width:260px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin:12px 0 0;color:#fff;text-transform:capitalize;text-align:center}.callerDetails h4{margin:0;color:#fff}.tx-black,.title{color:#000!important}.callerDetails p{margin-top:-3px;margin-bottom:0;color:#fff}.call-sec-btn,.mic-btn{position:relative;box-sizing:border-box;border:1px solid #cccbcb;background-color:transparent;border-radius:25px;padding:12px;box-shadow:6px 6px 10px -1px #bebebe26,-5px -4px 10px -1px #d2d2d226;width:50px;height:50px}.mic-btn{padding:5px;width:37px;height:37px}.receive-btn{background-color:#28a745!important;color:#fff!important}.receive-btn span{color:#fff!important}.scroll-container{width:100%;overflow:hidden;white-space:nowrap;position:relative}.scroll-text{display:inline-block;padding-left:100%;animation:scroll-left 12s linear infinite;font-size:16px}@keyframes scroll-left{0%{transform:translate(0)}to{transform:translate(-100%)}}.call-sec-btn span{color:#cccbcb}.call-btn{width:60px;height:60px;background-color:#fff;border-radius:30px;box-sizing:border-box;border:2px solid white;margin:0 16px}.end-call-btn{background-color:#e14e4e}.end-call-btn span{color:#fff!important}.call-btn span{color:#234de8}.btn-container{display:flex;flex-wrap:wrap;padding:0 30px}.key-btn{width:50px;height:50px;background-color:transparent;text-align:center;box-sizing:border-box;margin:0 18px;font-size:22px;display:flex;flex-direction:column;justify-content:center;align-items:center;font-family:Lato,sans-serif;font-weight:900;font-style:normal;color:#d3d3d3;cursor:pointer;opacity:.8}.call-action-btns{text-align:center}#call-input{background-color:transparent;border:none;outline:none;text-align:center;color:#fff}.sendDigit{position:relative;text-align:center;width:80%;margin:auto;background-color:#ffffff1a;padding:2px 0;border-radius:3px}.input-clear-btn{position:absolute;right:6px;color:#fff;cursor:pointer}#minimize-btn-div{position:absolute;right:14px;top:12px;z-index:10}.minimize-btn{color:#fff;cursor:pointer}.wave-container{position:absolute;bottom:-4px;overflow:hidden;width:100%}.waves{width:660px;position:relative;margin-bottom:-7px;height:40px;min-height:40px}.held-call-banner{position:absolute;top:0;left:0;right:0;background:#1644f09c;z-index:2100;box-shadow:0 4px 12px #0000004d;border-radius:0 0 16px 16px;max-height:220px;overflow-y:auto}.held-call-content{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:6px 6px 0;padding-bottom:6px;border-bottom:1px dotted #4b4b4b}.held-info{display:flex;align-items:center;gap:10px;flex:1}.hold-icon{font-size:24px;color:#fbbf24}.swap-icon{font-size:24px}.held-caller{display:flex;flex-direction:column;gap:2px}.held-label{font-size:10px;color:#ffffffb3;text-transform:uppercase;letter-spacing:.5px}.held-name{font-size:14px;font-weight:600;color:#fff}.held-number{font-size:13px;font-weight:500;color:#fff}.held-actions{display:flex;gap:8px;align-items:center}.held-btn{padding:6px 16px;border-radius:20px;border:none;font-size:13px;font-weight:600;cursor:pointer;transition:transform .2s,box-shadow .2s}.held-btn:hover{transform:scale(1.05);box-shadow:0 4px 12px #0003}.swap-btn{background:#3b82f6;color:#fff}.merge-btn{background:#10b981;color:#fff}.h-77px{height:77px}.incoming-banners-container{width:100%;padding:5px 8px;height:100%;gap:8px;overflow-y:auto}.call-container-model{width:385px!important;height:646px!important;margin:auto 0 0 1px;border-radius:20px;box-shadow:6px 6px 10px -1px #00000026,-5px -4px 10px -1px #00000026;display:flex;box-sizing:border-box;position:relative;overflow:hidden;justify-content:center;align-items:center}.incoming-banner{top:0;left:0;width:100%;right:0;background:linear-gradient(135deg,#1e3a8a 0%,#3b82f6 100%);padding:12px 16px;z-index:2000;box-shadow:0 4px 12px #0003;border-radius:16px}.incoming-banner-content{display:flex;align-items:center;justify-content:space-between;gap:12px}.incoming-info{flex:1;display:flex;flex-direction:column;gap:4px}.incoming-label{font-size:11px;color:#fffc;text-transform:uppercase;letter-spacing:.5px}.incoming-caller{display:flex;flex-direction:column;gap:2px}.caller-name{font-size:15px;font-weight:600;color:#fff}.caller-number{font-size:13px;color:#ffffffe6}.incoming-actions{display:flex;gap:8px;align-items:center}.banner-btn{width:44px;height:44px;border-radius:50%;border:none;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:transform .2s}.banner-btn:hover{transform:scale(1.1)}.banner-btn .material-symbols-outlined{font-size:20px}.accept-btn{background:#10b981}.accept-btn .material-symbols-outlined{color:#fff}.reject-btn{background:#ef4444}.reject-btn .material-symbols-outlined{color:#fff}.contacts-panel{position:absolute;top:0;bottom:12px;width:340px;background:#ffffff;border-radius:16px;box-shadow:0 10px 25px #00000026;display:flex;flex-direction:column;overflow:hidden;height:40.4rem;left:24.1rem;z-index:1000000}.contacts-header{height:56px;display:flex;align-items:center;justify-content:space-between;padding:0 16px;border-bottom:1px solid #f0f0f0}.contacts-header .title{font-weight:600}.contacts-header .back,.contacts-header .search{color:#9aa0a6;cursor:pointer}.disabled{opacity:.5;pointer-events:none}.contacts-list{padding:8px 8px 12px;overflow-y:auto}.contact-item{display:flex;align-items:center;padding:10px 8px;border-radius:10px}.contact-item:hover{background:#f7f9fc}.contact-avatar{width:37px;height:37px;border-radius:50%;object-fit:cover;margin-right:12px}.contact-info{flex:1}.contact-name{font-weight:600;color:#111827}.contact-title{font-size:12px;color:#6b7280}.contact-call-btn{display:inline-flex;align-items:center;gap:6px;background:#234de8;color:#fff;border:none;border-radius:16px;padding:8px;cursor:pointer}.contact-add-btn{background-color:#2ecc71!important}.conference-hold-contact{display:inline-flex;align-items:center;gap:5px;background:#727070;color:#fff;border:none;border-radius:50%;padding:7px;cursor:pointer}.conference-hold-contact.on-hold{background:#28a745!important;color:#fff}.user-info-section{width:100%;height:100%;overflow-y:auto;overflow-x:hidden!important}.user-info-section::-webkit-scrollbar{display:none}.toggle-btn{cursor:pointer}.text-container{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;transition:all .3s ease}.text-container.expanded{-webkit-line-clamp:unset}.userName{font-family:FontAwesome}.subject-text{display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden}.conference-contact{display:inline-flex;align-items:center;gap:5px;background:#e14e4e;color:#fff;border:none;border-radius:50%;padding:7px;cursor:pointer}.organizer-label{padding:1px 5px;font-size:11px;border-radius:10px;border:1px solid #a0a0a0;margin-top:2px;background:#fcfcfc}.contact-call-btn .material-symbols-outlined{font-size:18px;color:#fff}.contact-call-btn .label{font-size:12px}.parallax>use{animation:move-forever 25s cubic-bezier(.55,.5,.45,.5) infinite}.parallax>use:nth-child(1){animation-delay:-2s;animation-duration:7s}.parallax>use:nth-child(2){animation-delay:-3s;animation-duration:10s}.parallax>use:nth-child(3){animation-delay:-4s;animation-duration:13s}.parallax>use:nth-child(4){animation-delay:-5s;animation-duration:20s}@keyframes move-forever{0%{transform:translate3d(-90px,0,0)}to{transform:translate3d(85px,0,0)}}.animated-margin{transition:margin-top .5s ease}app-incoming-call{position:absolute;top:0;left:0;width:100%;height:100%;background-color:transparent;z-index:1001}.min-call-container{width:320px;height:124px;border-radius:20px;box-shadow:6px 6px 10px -1px #00000026,-5px -4px 10px -1px #00000026;display:flex;flex-direction:column;box-sizing:border-box;position:relative;overflow:hidden;margin:auto;align-items:center;padding:12px 16px;color:#fff}.min-call-animation{background:#fff;width:48px;height:48px;position:relative;margin:0 12px 0 auto;border-radius:100%;border:solid 2px #fff}.min-avatar-img{width:46px;height:46px;border-radius:100%;position:absolute;left:0;top:0}.min-callerDetails{color:#fff;display:flex;flex-direction:column;align-items:flex-start}.name{width:170px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:20px;margin:0;color:#fff}.min-callerDetails p{margin:0;color:#fff}.min-btn-container{position:relative;display:flex;width:100%;justify-content:flex-start;align-items:center;margin-top:6px}.min-call-sec-btn{width:40px;height:40px;box-sizing:border-box;border:1px solid #cccbcb;background-color:transparent;border-radius:20px;display:flex;align-items:center;justify-content:center;margin-right:12px;box-shadow:6px 6px 10px -1px #bebebe26,-5px -4px 10px -1px #d2d2d226}.min-call-sec-btn span{color:#cccbcb}.min-call-btn{width:40px;height:40px;border-radius:20px;box-sizing:border-box;border:2px solid white;display:flex;align-items:center;justify-content:center}.fullscreen{position:absolute;right:18px;top:14px;color:#e8e8e8;font-size:18px;cursor:pointer}.btn-container{display:flex;flex-wrap:wrap;padding:0 24px}.dial-btn{width:40px;height:40px;background-color:transparent;text-align:center;box-sizing:border-box;margin:4px 25px;font-size:24px;display:flex;flex-direction:column;justify-content:center;align-items:center;font-family:Lato,sans-serif;font-weight:900;font-style:normal;color:#b5b5b5;cursor:pointer}.btn-albhabets{font-family:Lato,sans-serif;font-size:12px;font-weight:400}.min-timer{width:50px;font-size:18px;margin-right:10px;border-radius:4px;height:35px;display:flex;align-items:center}.record-action-btns{display:flex;flex-direction:column;align-items:center}.record-btn-container{position:relative}.record-btn{border:none;border-radius:50%;width:50px;height:50px;display:flex;align-items:center;justify-content:center;cursor:pointer;margin:0 5px;position:relative;overflow:hidden}.record-btn.start-stop .recording-icon{width:50%;height:50%;border-radius:50%;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}.record-btn.start-stop.recording .recording-icon{background-color:#000}.record-btn.start-stop.recording{border:3px solid #000}.record-btn.start-stop.stopped .recording-icon{background-color:red;border:3px solid #ff0000;border-radius:50%;position:absolute}.record-btn.start-stop.stopped{border:3px solid #ff0000}.record-btn.start-stop.stopped .recording-icon{width:40%;height:40%;border-radius:0;background-color:red}.pause-resume-btns{display:flex;flex-direction:column;align-items:center;margin-top:10px}.record-btn.pause-resume{border:none;border-radius:50%;width:50px;height:50px;background:white;display:flex;align-items:center;justify-content:center;margin:5px 0}.record-btn.pause-resume .material-symbols-outlined{font-size:20px;color:#000}.timer-display{font-size:1.2em;margin-top:10px;color:#000}.w-40{width:40%}.w-60{width:60%}.callToNum{color:#fff;font-weight:400;text-align:center}.callToNum span{font-weight:600}.conference-call-view{display:flex;flex-direction:column;align-items:center;justify-content:flex-start;width:100%;padding:12px 16px 35px;color:#fff;height:100%}.conf-heading{display:flex;align-items:center;gap:8px;margin-top:8px}.conf-icon{color:#4579aa;font-size:32px;width:50px;height:50px;border:1px solid gray;border-radius:50%;display:flex;align-items:center;justify-content:center;background:#e1e1e1}.conf-title{font-weight:600;font-size:20px}.conf-name{margin-top:10px;font-size:17px;font-weight:600;text-align:center}.conf-timer{margin-top:4px;font-size:12px;opacity:.9}.conf-record{margin-top:14px}.record-stop-btn{width:44px;height:44px;border-radius:50%;border:none;background:#fff;display:flex;align-items:center;justify-content:center}.record-stop-btn .material-symbols-outlined{color:#e14e4e;font-size:28px}.conf-remove{margin-top:8px}.remove-btn{background:#ff0000!important;color:#fff;border:none;border-radius:6px;padding:6px 12px;font-size:12px;width:82px!important;height:auto}.conf-actions{margin-top:14px;display:flex;align-items:center;justify-content:center;gap:18px}.circle-btn{width:56px;height:56px;border-radius:50%;border:none;background:#000;display:flex;align-items:center;justify-content:center}.circle-btn .material-symbols-outlined{color:#fff;font-size:24px}.circle-btn.active{opacity:.85}.conf-end{margin-top:16px}.circle-btn.danger{background:#e14e4e}.circle-btn.danger .material-symbols-outlined{color:#fff}\n"] }]
|
|
3225
|
+
args: [{ selector: 'lib-call-progress', template: "<div class=\"d-flex\">\r\n <div class=\"call-container\" *ngIf=\"!isMinimised && currentCallList?.length\"\r\n [ngClass]=\"{'collops': isCollops, 'incoming-call-container': isClickExpand, 'contacts-open': showContactsPanel }\">\r\n <!-- <ng-container *ngIf=\"!incomingCallDiv || isConcurrentIncoming || true\"> -->\r\n\r\n <!-- All type Call Hold list -->\r\n <div class=\"held-call-banner\"\r\n *ngIf=\"currentCallList.length > 1 && !!currentCall && ((isConferenceCallHold || isConference) || !isConference)\">\r\n <ng-container *ngFor=\"let conf of conferenceCallList\">\r\n <div class=\"held-call-content\" *ngIf=\"conf?.isConferenceHold\">\r\n <div class=\"held-info\">\r\n <span class=\"material-symbols-outlined hold-icon\">pause_circle</span>\r\n <div class=\"held-caller\">\r\n <span class=\"held-label\">Hold</span>\r\n <span class=\"held-name\">Conference Call</span>\r\n </div>\r\n </div>\r\n <div class=\"held-actions\">\r\n <button class=\"conference-hold-contact\" [ngClass]=\"{ 'on-hold': conf?.isConferenceHold }\"\r\n (click)=\"swapCalls(conf,true)\">\r\n <span class=\"material-symbols-outlined\" title=\"{{'Hold'}}\"> phone_paused </span>\r\n </button>\r\n <button class=\"conference-contact\" (click)=\"endCall(true)\">\r\n <span class=\"material-symbols-outlined\" title=\"Call End\"> call_end </span>\r\n </button>\r\n <div class=\"togglearrow-arrow me-2\" id=\"togglearrow\" (click)=\"toggleContactsPanel(conf)\">\r\n <i class=\"fa fa-angle-right\"></i>\r\n </div>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- For single incoming call -->\r\n <div class=\"h-100 py-5\" style=\"display: flex; flex-direction: column;\"\r\n *ngIf=\"currentCallList.length === 1 && currentCallList[0]?.isIncomingCall && !currentCallList[0]?.isAcceptCall \">\r\n <div class=\"callToNum\">Incoming call on <br /><span>{{currentCallList[0]?.to || 'Unknown\r\n Number'}}</span>\r\n </div>\r\n <div class=\"call-animation\" [ngClass]=\"{'call-animation-play': showRingAnimation}\">\r\n <img class=\"avatar-img\" [src]=\"currentCallList[0]?.img || 'assets/images/user.jpg'\" alt=\"\"\r\n width=\"120\" />\r\n </div>\r\n <div class=\"callerDetails\">\r\n <h1>{{ currentCallList[0]?.name ? currentCallList[0]?.name : currentCallList[0]?.phone || 'Unknown\r\n Number' }}</h1>\r\n <p *ngIf=\"!!currentCallList[0]?.name\">{{ currentCallList[0]?.phone }}</p>\r\n </div>\r\n\r\n <div class=\"call-action-btns mt-auto\">\r\n <button class=\"call-btn receive-btn\" *ngIf=\"!newIncomingCallsList[0]?.isCallConnected\"\r\n [disabled]=\"isIncomingCallBtnDisable\">\r\n <span class=\"material-symbols-outlined\" (click)=\"add(currentCallList[0])\"> call </span>\r\n </button>\r\n <button class=\"call-btn reject-btn\">\r\n <span class=\"material-symbols-outlined\" (click)=\"onEndCall(currentCallList[0])\"> call_end\r\n </span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- For single active call -->\r\n <div *ngIf=\"(!isConference || isConferenceCallHold) && (!!currentCall?.id && !currentCall?.isConference) && currentCall?.isAcceptCall\"\r\n [ngStyle]=\"{'display': 'flex', 'flex-direction': 'column', 'position': 'relative'}\" class=\"active-call\">\r\n\r\n <div class=\"call-animation\" [ngClass]=\"{'call-animation-play': showRingAnimation}\">\r\n <img class=\"avatar-img\" [src]=\"currentCall?.img || 'assets/images/user.jpg'\" alt=\"\" width=\"120\" />\r\n </div>\r\n <div class=\"callerDetails\">\r\n <h1 [ngStyle]=\"{'margin-top': showKeypad ? '0': '8px'}\">{{currentCall?.name || 'Unknown number'}}\r\n </h1>\r\n <p>{{currentCall?.phone }}</p>\r\n <h4 style=\"margin-top: 4px\">{{currentCall?.time || timer}}</h4>\r\n </div>\r\n\r\n <div class=\"record-action-btns\" *ngIf=\"!showKeypad\" [ngStyle]=\"{'margin-top': showKeypad ? '0': '20px'}\">\r\n <div class=\"record-btn-container\">\r\n <button class=\"record-btn start-stop\" *ngIf=\"!isRecording\"\r\n [ngClass]=\"{'recording': isRecording, 'stopped': !isRecording}\" (click)=\"toggleRecording()\"\r\n [title]=\"isRecording ? 'Stop Recording' : 'Start Recording'\"\r\n [disabled]=\"!currentCall?.isAcceptCall\">\r\n <span class=\"recording-icon\"></span>\r\n </button>\r\n <div class=\"pause-resume-btns\">\r\n <button class=\"record-btn pause-resume\" *ngIf=\"isRecording && !isPaused\"\r\n (click)=\"pauseRecording()\">\r\n <span class=\"material-symbols-outlined\"> pause </span>\r\n </button>\r\n <button class=\"record-btn pause-resume\" *ngIf=\"isPaused\" (click)=\"resumeRecording()\">\r\n <span class=\"material-symbols-outlined\"> play_arrow </span>\r\n </button>\r\n </div>\r\n </div>\r\n <div *ngIf=\"isRecording\" class=\"timer-display\">\r\n {{ getFormattedTime() }}\r\n </div>\r\n </div>\r\n <div *ngIf=\"showKeypad\" class=\"sendDigit\">\r\n <input type=\"text\" name=\"call-inputs\" id=\"call-input\" [(ngModel)]=\"callInput\"\r\n (keyup)=\"onCallInputEnter($event)\">\r\n <span class=\"material-symbols-outlined input-clear-btn\" *ngIf=\"callInput\"\r\n (click)=\"clearInputs()\">close_small</span>\r\n </div>\r\n <div class=\"btn-container justify-content-center\" *ngIf=\"showKeypad\">\r\n <div class=\"key-btn\" *ngFor=\"let key of keypadVal\" (click)=\"onCallInputs(key.num)\">\r\n {{key.num}}\r\n <span class=\"btn-albhabets\">{{key.text ? key.text : ' '}}</span>\r\n </div>\r\n </div>\r\n\r\n <div class=\"call-action-btns\" [ngStyle]=\"{'margin-top': showKeypad ? '0': '723x'}\">\r\n <!-- <div class=\"mb-3\" *ngIf=\"!incomingCallDiv || isConcurrentIncoming\">\r\n <button class=\"held-btn merge-btn\" (click)=\"mergeCalls()\" title=\"Merge calls\"\r\n [disabled]=\"isMergeCallAllowed() || currentCallList.length < 2\">\r\n <span>Merge</span>\r\n </button>\r\n </div> -->\r\n <div class=\"flex align-items-center justify-content-evenly mb-3\">\r\n <button class=\"call-sec-btn mr-3\" [disabled]=\"!currentCall?.isAcceptCall\" (click)=\"toggleMute()\">\r\n <span class=\"material-symbols-outlined\" *ngIf=\"isMute\"> mic_off </span>\r\n <span class=\"material-symbols-outlined\" *ngIf=\"!isMute\"> mic </span>\r\n\r\n </button>\r\n <button class=\"call-sec-btn mr-3\" [disabled]=\"!currentCall?.isAcceptCall\">\r\n <span class=\"material-symbols-outlined\" (click)=\"toggleKeypad()\"> transition_dissolve\r\n </span>\r\n </button>\r\n <button class=\"call-sec-btn\" [disabled]=\"!currentCall?.isAcceptCall\"\r\n (click)=\"toggleContactsPanel(currentCall)\">\r\n <span class=\"material-symbols-outlined\"> groups_2 </span>\r\n </button>\r\n </div>\r\n\r\n <div>\r\n <button class=\"call-btn end-call-btn\" [disabled]=\"!currentCall?.isAcceptCall\" (click)=\"endCall()\">\r\n <span class=\"material-symbols-outlined\"> call_end </span>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- conference call view -->\r\n <div class=\"conference-call-view\" *ngIf=\"isConference && currentCall?.isConference\">\r\n <div class=\"conf-heading\">\r\n <span class=\"conf-icon material-symbols-outlined\"> groups </span>\r\n <span class=\"conf-title\">Conference Call</span>\r\n </div>\r\n\r\n <div class=\"scroll-container\">\r\n <div class=\"scroll-text conf-name\">\r\n <ng-container *ngFor=\"let call of currentCallList; let i = index\">\r\n <ng-container *ngIf=\"!call?.isConferenceHold\">\r\n <span *ngIf=\"i != 0\">&</span>\r\n {{call?.name ? call?.name : call?.phone || 'Unknown number'}}\r\n </ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n <div class=\"conf-timer\">{{ timer }}</div>\r\n <div class=\"record-action-btns mt-auto\" *ngIf=\"!showKeypad\"\r\n [ngStyle]=\"{'margin-top': showKeypad ? '0': '20px'}\">\r\n <div class=\"record-btn-container\">\r\n <button class=\"record-btn start-stop\" *ngIf=\"!isRecording\"\r\n [ngClass]=\"{'recording': isRecording, 'stopped': !isRecording}\" (click)=\"toggleRecording()\"\r\n [title]=\"isRecording ? 'Stop Recording' : 'Start Recording'\">\r\n <span class=\"recording-icon\"></span>\r\n </button>\r\n <div class=\"pause-resume-btns\">\r\n <button class=\"record-btn pause-resume\" *ngIf=\"isRecording && !isPaused\"\r\n (click)=\"pauseRecording()\">\r\n <span class=\"material-symbols-outlined\"> pause </span>\r\n </button>\r\n <button class=\"record-btn pause-resume\" *ngIf=\"isPaused\" (click)=\"resumeRecording()\">\r\n <span class=\"material-symbols-outlined\"> play_arrow </span>\r\n </button>\r\n </div>\r\n </div>\r\n <div *ngIf=\"isRecording\" class=\"timer-display\">\r\n {{ getFormattedTime() }}\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"showKeypad\" class=\"sendDigit mt-2\">\r\n <input type=\"text\" name=\"call-inputs\" id=\"call-input\" [(ngModel)]=\"callInput\"\r\n (keyup)=\"onCallInputEnter($event)\">\r\n <span class=\"material-symbols-outlined input-clear-btn\" *ngIf=\"callInput\"\r\n (click)=\"clearInputs()\">close_small</span>\r\n </div>\r\n <div class=\"btn-container justify-content-center\" *ngIf=\"showKeypad\">\r\n <div class=\"key-btn\" *ngFor=\"let key of keypadVal\" (click)=\"onCallInputs(key.num)\">\r\n {{key.num}}\r\n <span class=\"btn-albhabets\">{{key.text ? key.text : ' '}}</span>\r\n </div>\r\n </div>\r\n\r\n <div class=\"conf-actions\">\r\n <button class=\"circle-btn\" [ngClass]=\"{'active': isMute}\" (click)=\"toggleMute(true)\">\r\n <span class=\"material-symbols-outlined\"> {{ isMute ? 'mic_off' : 'mic' }} </span>\r\n </button>\r\n <button class=\"circle-btn\" (click)=\"toggleKeypad()\">\r\n <span class=\"material-symbols-outlined\"> transition_dissolve </span>\r\n </button>\r\n <button class=\"circle-btn\" (click)=\"toggleContactsPanel(currentCall)\">\r\n <span class=\"material-symbols-outlined\"> groups_2 </span>\r\n </button>\r\n </div>\r\n\r\n <div class=\"conf-end\">\r\n <button class=\"circle-btn danger\" (click)=\"endConfereneceCall()\">\r\n <span class=\"material-symbols-outlined\"> call_end </span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"wave-container\">\r\n <svg class=\"waves\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\r\n viewBox=\"0 24 150 28\" preserveAspectRatio=\"none\" shape-rendering=\"auto\">\r\n <defs>\r\n <path id=\"gentle-wave\"\r\n d=\"M-160 44c30 0 58-18 88-18s 58 18 88 18 58-18 88-18 58 18 88 18 v44h-352z\" />\r\n </defs>\r\n <g class=\"parallax\">\r\n <use xlink:href=\"#gentle-wave\" x=\"48\" y=\"0\" fill=\"rgba(255,255,255,0.7)\" />\r\n <use xlink:href=\"#gentle-wave\" x=\"48\" y=\"3\" fill=\"rgba(255,255,255,0.5)\" />\r\n <use xlink:href=\"#gentle-wave\" x=\"48\" y=\"7\" fill=\"#fff\" />\r\n </g>\r\n </svg>\r\n </div>\r\n <!-- </ng-container> -->\r\n </div>\r\n\r\n <!-- Incoming call user details shown in model -->\r\n <div class=\"call-container-model p-3 text-white model-content call-container\" *ngIf=\"isClickExpand\">\r\n <div class=\"mb-2 user-info-section\">\r\n <div class=\"text-center my-3\">\r\n <h3 class=\"text-white\">C2C -POINT {{selectedUserInfo?.pointName}}</h3>\r\n </div>\r\n <div class=\"mb-3\">\r\n <h5 class=\"text-white mb-1\">Name:</h5>\r\n <h4 class=\"text-white userName\">{{selectedUserInfo?.name}}</h4>\r\n </div>\r\n <div class=\"f-13\">\r\n <div class=\"row mb-3\">\r\n <div class=\"col-6 mb-2\">\r\n <div class=\"mb-1\">Number:</div>\r\n <div class=\"\">{{selectedUserInfo?.number}}</div>\r\n </div>\r\n <div class=\"col-6 mb-2\">\r\n <div class=\"mb-1\">Extension:</div>\r\n <div class=\"ml-2\">{{selectedUserInfo?.extension}}</div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"row mb-3\">\r\n <div class=\"col-12 mb-2\">\r\n <div class=\"me-2\">Email: </div>\r\n <div>{{selectedUserInfo?.email}}</div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"row mb-3\">\r\n <div class=\"col-12 mb-2\">\r\n <div class=\"me-2\">Subject:</div>\r\n <div class=\"ml-2 subject-text\" title=\"{{selectedUserInfo?.subject}}\">\r\n {{selectedUserInfo?.subject}}</div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"row mb-3\">\r\n <div class=\"col-12 mb-2\">\r\n <div class=\"me-2 mb-1\">Image:</div>\r\n <div class=\"text-ellipsis\">\r\n <ng-container\r\n *ngIf=\"selectedUserInfo?.image && selectedUserInfo?.image !== '-'; else noImage\">\r\n <img src=\"{{selectedUserInfo?.image}}\" alt=\"\" width=\"150\" class=\"ml-2\" />\r\n </ng-container>\r\n <ng-template #noImage>\r\n <span class=\"ml-2\">No Image Available</span>\r\n </ng-template>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\" mb-4\">\r\n <div class=\"\">\r\n <div class=\"mb-1\">Message:</div>\r\n <div>\r\n <div class=\"text-container\" [class.expanded]=\"isExpanded\">{{selectedUserInfo?.message}}\r\n </div>\r\n <small class=\"toggle-btn\" *ngIf=\"showButton\" (click)=\"toggleText()\">{{ isExpanded ? 'See\r\n less' : 'See more' }}</small>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"row mb-3\">\r\n <div class=\"col-6 mb-2\">\r\n <div class=\"mb-1\">Point Name:</div>\r\n <div class=\"\">{{selectedUserInfo?.pointName}}</div>\r\n </div>\r\n <div class=\"col-6 mb-2\">\r\n <div class=\"mb-1\">Source Name:</div>\r\n <div class=\"\">{{selectedUserInfo?.sourceName}}</div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- contact list panel -->\r\n <div class=\"contacts-panel\" *ngIf=\"showContactsPanel\">\r\n <div class=\"contacts-header\">\r\n <div>Participent</div>\r\n <div class=\"d-flex justify-content-between\">\r\n <p></p>\r\n <span class=\"material-symbols-outlined dial-close-btn\" (click)=\"toggleContactsPanel({}, true)\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\" width=\"24px\"\r\n fill=\"#000000\">\r\n <path\r\n d=\"m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z\" />\r\n </svg>\r\n </span>\r\n </div>\r\n </div>\r\n\r\n <!-- SEARCH INPUT (visible when isSearchVisible = true) -->\r\n <div class=\"search-bar p-3\">\r\n <input type=\"text\" placeholder=\"Search...\" [(ngModel)]=\"searchText\" (input)=\"applyFilter()\" />\r\n <ng-container *ngFor=\"let c of filteredList\">\r\n <div class=\"contact-item\" *ngIf=\"isDirectCallOptionShow && searchText\">\r\n <img class=\"contact-avatar\" [src]=\"c?.img || 'assets/images/user.jpg'\" alt=\"\" />\r\n <div class=\"contact-info\">\r\n <div class=\"contact-name\">{{c?.firstName}} {{c?.middleName}} {{c?.lastName}}</div>\r\n <div class=\"contact-title\">{{ (c?.numbersList && c?.numbersList[0]?.number)}}</div>\r\n </div>\r\n <button class=\"contact-call-btn contact-add-btn mr-2\" (click)=\"callContact(c)\"\r\n *ngIf=\"!c?.IsConnected\" title=\"Add to conference call\">\r\n <span class=\"material-symbols-outlined\"> add </span>\r\n </button>\r\n <button class=\"contact-call-btn\" (click)=\"CallToUnsavedNumber(c?.numbersList[0]?.number, true)\"\r\n *ngIf=\"!c?.IsConnected\" title=\"New Call\">\r\n <span class=\"material-symbols-outlined\"> call </span>\r\n </button>\r\n </div>\r\n </ng-container>\r\n <ng-container *ngIf=\"!filteredList.length\">\r\n <div class=\"contact-item\" *ngIf=\"searchText\">\r\n <img class=\"contact-avatar\" [src]=\"'assets/images/user.jpg'\" alt=\"\" />\r\n <div class=\"contact-info\">\r\n <div class=\"contact-title\">{{ searchText }}</div>\r\n </div>\r\n <button class=\"contact-call-btn contact-add-btn mr-2\" (click)=\"CallToUnsavedNumber(searchText)\"\r\n title=\"Add to conference call\">\r\n <span class=\"material-symbols-outlined\"> add </span>\r\n </button>\r\n <button class=\"contact-call-btn\" (click)=\"CallToUnsavedNumber(searchText, true)\" title=\"New Call\">\r\n <span class=\"material-symbols-outlined\"> call </span>\r\n </button>\r\n </div>\r\n </ng-container>\r\n </div>\r\n <div class=\"contacts-list\">\r\n <div class=\"px-2\">\r\n <h5 class=\"mb-0 title\">In This Call</h5>\r\n </div>\r\n <hr class=\"mb-2 mt-1\">\r\n <ng-container *ngFor=\"let c of filteredParticipentList\">\r\n <div class=\"contact-item\" *ngIf=\"!c?.isLeft\">\r\n <ng-container *ngIf=\"c?.to == 'client' else participentInfo\">\r\n <img class=\"contact-avatar\" [src]=\"c?.fromImage || 'assets/images/user.jpg'\" alt=\"\" />\r\n <div class=\"contact-info\">\r\n <div class=\"contact-name\">You\r\n </div>\r\n <div class=\"contact-title\">{{ c?.from }}</div>\r\n </div>\r\n <button class=\"mic-btn mr-2\" [disabled]=\"c?.hold\" (click)=\"onMuteUser(c)\">\r\n <span class=\"material-symbols-outlined\" *ngIf=\"c?.isMute\"> mic_off </span>\r\n <span class=\"material-symbols-outlined\" *ngIf=\"!c?.isMute\"> mic </span>\r\n </button>\r\n <button class=\"conference-hold-contact mr-2\" [ngClass]=\"{ 'on-hold': c?.hold }\"\r\n (click)=\"onHoldCall(c)\">\r\n <span class=\"material-symbols-outlined\" [title]=\"!c?.hold ? 'Hold' : 'Resume'\"> phone_paused\r\n </span>\r\n </button>\r\n <button class=\"conference-contact\" (click)=\"onEndCall(c, false, true)\">\r\n <span class=\"material-symbols-outlined\" title=\"Call End\"> call_end </span>\r\n </button>\r\n </ng-container>\r\n <ng-template #participentInfo>\r\n <img class=\"contact-avatar\"\r\n [src]=\"c?.direction == 'outgoing-call' ? c?.toImage || 'assets/images/user.jpg' : c?.fromImage || 'assets/images/user.jpg'\"\r\n alt=\"\" />\r\n <div class=\"contact-info\">\r\n <div class=\"contact-name\">{{c?.direction == 'outgoing-call' ? c?.toName || 'Unknown' :\r\n c?.fromName || 'Unknown'}}\r\n </div>\r\n <div class=\"contact-title\" *ngIf=\"c?.to != 'c2c_softphone_client'\">{{ c?.direction ==\r\n 'outgoing-call' ? c?.to || 'Unknown' : c?.from ||\r\n 'Unknown'}}</div>\r\n <div class=\"contact-title\" *ngIf=\"c?.to == 'c2c_softphone_client'\">{{ c?.from ||\r\n 'Unknown'}}</div>\r\n <div class=\"d-flex\" *ngIf=\"c?.from == hostnumber?.from && c?.to == 'c2c_softphone_client'\">\r\n <span class=\"organizer-label\">Organizer</span>\r\n </div>\r\n </div>\r\n <button class=\"mic-btn mr-2\" [disabled]=\"c?.hold\" (click)=\"onMuteUser(c)\">\r\n <span class=\"material-symbols-outlined\" *ngIf=\"c?.isMute\"> mic_off </span>\r\n <span class=\"material-symbols-outlined\" *ngIf=\"!c?.isMute\"> mic </span>\r\n </button>\r\n <button class=\"conference-hold-contact mr-2\" [ngClass]=\"{ 'on-hold': c?.hold }\"\r\n (click)=\"onHoldCall(c)\" *ngIf=\"c?.to != 'c2c_softphone_client'\">\r\n <span class=\"material-symbols-outlined\" [title]=\"!c?.hold ? 'Hold' : 'Resume'\"> phone_paused\r\n </span>\r\n </button>\r\n <button class=\"conference-contact\" (click)=\"onEndCall(c, false, true)\"\r\n *ngIf=\"(c?.to == 'c2c_softphone_client' && deviceNumberList.includes(c?.from)) || c?.to != 'c2c_softphone_client'\">\r\n <span class=\"material-symbols-outlined\" title=\"Call End\"> call_end </span>\r\n </button>\r\n </ng-template>\r\n </div>\r\n </ng-container>\r\n <hr class=\"m-2\">\r\n <div class=\"mt-3 px-2\">\r\n <h5 class=\"mb-0 title\">Participent added to the call</h5>\r\n </div>\r\n <hr class=\"mb-2 mt-1\">\r\n <ng-container *ngFor=\"let c of filteredParticipentList\">\r\n <div class=\"contact-item\" *ngIf=\"c?.isLeft\">\r\n <img class=\"contact-avatar\"\r\n [src]=\"c.direction == 'outgoing-call' ? c?.toImage || 'assets/images/user.jpg' : c?.fromImage || 'assets/images/user.jpg'\"\r\n alt=\"\" />\r\n <div class=\"contact-info\">\r\n <div class=\"contact-name\">{{c.direction == 'outgoing-call' ? c?.toName : c?.fromName || 'Unknown\r\n number'}}</div>\r\n <div class=\"contact-title\">{{c.direction == 'outgoing-call' ? c?.to : c?.from}}</div>\r\n </div>\r\n <button class=\"contact-call-btn contact-add-btn \"\r\n (click)=\"CallToUnsavedNumber(c.direction == 'outgoing-call' ? c?.to : c?.from)\">\r\n <span class=\"material-symbols-outlined\"> add </span>\r\n <span class=\"label\">Add</span>\r\n </button>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div class=\"min-call-container\" *ngIf=\"isMinimised\">\r\n <span class=\"material-symbols-outlined fullscreen\" (click)=\"maximiseDialpad()\"> open_in_full </span>\r\n <div style=\"display: flex; width: 100%\">\r\n <div>\r\n <div class=\"min-call-animation\" id=\"call-avatar\">\r\n <img class=\"min-avatar-img\" [src]=\"callData.img\" alt=\"\" />\r\n </div>\r\n </div>\r\n <div>\r\n <div class=\"min-callerDetails\">\r\n <div class=\"name\">\r\n {{callData.name}}\r\n </div>\r\n <p style=\"margin: 0\">{{callData.displayNum ? callData.displayNum : callData.phone }}</p>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"min-btn-container\">\r\n <div class=\"min-timer\">{{timer}}</div>\r\n <button class=\"min-call-sec-btn\" (click)=\"toggleMute()\" [disabled]=\"disbaleEndCallBtn\">\r\n <span class=\"material-symbols-outlined\" *ngIf=\"isMute\"> mic_off </span>\r\n <span class=\"material-symbols-outlined\" *ngIf=\"!isMute\"> mic </span>\r\n </button>\r\n <button class=\"min-call-btn end-call-btn\" [disabled]=\"disbaleEndCallBtn\" (click)=\"endCall()\">\r\n <span class=\"material-symbols-outlined\"> call_end </span>\r\n </button>\r\n </div>\r\n</div>\r\n<!-- Call Disconnect Modal -->\r\n<div class=\"custom-modal\" *ngIf=\"showDisconnectModal\">\r\n <div class=\"modal-content p-3\">\r\n <div class=\"contacts-header p-0 pb-2\">\r\n <h4 class=\"title mb-0\">Call Disconnected</h4>\r\n <div class=\"d-flex justify-content-between\">\r\n <span class=\"material-symbols-outlined dial-close-btn\" (click)=\"showDisconnectModal = false\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\" width=\"24px\"\r\n fill=\"#000000\">\r\n <path\r\n d=\"m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z\" />\r\n </svg>\r\n </span>\r\n </div>\r\n </div>\r\n\r\n <p class=\"mt-2\">\r\n You can end conference call or leave conference call.\r\n </p>\r\n\r\n <div class=\"button-group\">\r\n <button class=\"btn end-btn\" (click)=\"endConference()\">\r\n <span class=\"material-symbols-outlined mr-2\"> call_end </span>\r\n End All\r\n </button>\r\n\r\n <button class=\"btn end-btn\" (click)=\"leaveConference()\">\r\n <span class=\"material-symbols-outlined mr-2\"> call_end </span>\r\n Leave\r\n </button>\r\n </div>\r\n\r\n </div>\r\n</div>", styles: [".call-container{width:385px;height:646px!important;margin:auto;border-radius:20px;box-shadow:6px 6px 10px -1px #00000026,-5px -4px 10px -1px #00000026;display:flex;box-sizing:border-box;position:relative;justify-content:center;align-items:center;z-index:1000;flex-flow:column;overflow:hidden}.call-to-text{padding:6px 10px;border:1px solid #c2c2c2;border-radius:20px;font-size:13px}.collops{height:660px!important}.incoming-call-container{flex-flow:row!important}.active-call{width:385px!important}.call-animation{background:#fff;width:100px;height:100px;position:relative;margin:20px auto 0;border-radius:100%;border:solid 4px #fff;display:flex;align-items:center;justify-content:center}.call-animation:before{position:absolute;content:\"\";top:0;left:0;width:100%;height:100%;backface-visibility:hidden;border-radius:50%}.call-animation-play{animation:play 3s linear infinite}.call-info-wrapper{height:20px;overflow-y:auto;background:white;transition:height 1s}.open-collops{height:180px!important}.avatar-img{width:94px;height:94px;border-radius:100%}@keyframes play{0%{transform:scale(1)}15%{box-shadow:0 0 0 2px #fff6}25%{box-shadow:0 0 0 4px #fff6,0 0 0 8px #fff3}25%{box-shadow:0 0 0 8px #fff6,0 0 0 16px #fff3}50%{box-shadow:0 0 0 10px #fff6,0 0 0 20px #fff3}to{box-shadow:0 0 0 10px #fff6,0 0 0 20px #fff3;transform:scale(1.1);opacity:0}}.callerDetails{margin-top:8px;color:#fff;display:flex;flex-direction:column;align-items:center}.togglearrow-arrow{left:100%;background-color:#fff;width:25px;height:25px;text-align:center;cursor:pointer;border:1px solid #ccc;border-radius:50%;line-height:22px}.togglearrow-arrow.disabled{opacity:.3;cursor:not-allowed;pointer-events:none}.search-bar input{width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;outline:none;margin-bottom:10px}.togglearrow-arrow.disabled:hover{opacity:.3;cursor:not-allowed}.callerDetails h1{width:260px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin:12px 0 0;color:#fff;text-transform:capitalize;text-align:center}.callerDetails h4{margin:0;color:#fff}.tx-black,.title{color:#000!important}.callerDetails p{margin-top:-3px;margin-bottom:0;color:#fff}.call-sec-btn,.mic-btn{position:relative;box-sizing:border-box;border:1px solid #cccbcb;background-color:transparent;border-radius:25px;padding:12px;box-shadow:6px 6px 10px -1px #bebebe26,-5px -4px 10px -1px #d2d2d226;width:50px;height:50px}.mic-btn{padding:5px;width:37px;height:37px}.receive-btn{background-color:#28a745!important;color:#fff!important}.receive-btn span{color:#fff!important}.scroll-container{width:100%;overflow:hidden;white-space:nowrap;position:relative}.scroll-text{display:inline-block;padding-left:100%;animation:scroll-left 12s linear infinite;font-size:16px}@keyframes scroll-left{0%{transform:translate(0)}to{transform:translate(-100%)}}.call-sec-btn span{color:#cccbcb}.call-btn{width:60px;height:60px;background-color:#fff;border-radius:30px;box-sizing:border-box;border:2px solid white;margin:0 16px}.end-call-btn{background-color:#e14e4e}.end-call-btn span{color:#fff!important}.call-btn span{color:#234de8}.btn-container{display:flex;flex-wrap:wrap;padding:0 30px}.key-btn{width:50px;height:50px;background-color:transparent;text-align:center;box-sizing:border-box;margin:0 18px;font-size:22px;display:flex;flex-direction:column;justify-content:center;align-items:center;font-family:Lato,sans-serif;font-weight:900;font-style:normal;color:#d3d3d3;cursor:pointer;opacity:.8}.call-action-btns{text-align:center}#call-input{background-color:transparent;border:none;outline:none;text-align:center;color:#fff}.sendDigit{position:relative;text-align:center;width:80%;margin:auto;background-color:#ffffff1a;padding:2px 0;border-radius:3px}.input-clear-btn{position:absolute;right:6px;color:#fff;cursor:pointer}#minimize-btn-div{position:absolute;right:14px;top:12px;z-index:10}.minimize-btn{color:#fff;cursor:pointer}.wave-container{position:absolute;bottom:-4px;overflow:hidden;width:100%}.waves{width:660px;position:relative;margin-bottom:-7px;height:40px;min-height:40px}.held-call-banner{position:absolute;top:0;left:0;right:0;background:#1644f09c;z-index:2100;box-shadow:0 4px 12px #0000004d;border-radius:0 0 16px 16px;max-height:220px;overflow-y:auto}.held-call-content{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:6px 6px 0;padding-bottom:6px;border-bottom:1px dotted #4b4b4b}.held-info{display:flex;align-items:center;gap:10px;flex:1}.hold-icon{font-size:24px;color:#fbbf24}.swap-icon{font-size:24px}.held-caller{display:flex;flex-direction:column;gap:2px}.held-label{font-size:10px;color:#ffffffb3;text-transform:uppercase;letter-spacing:.5px}.held-name{font-size:14px;font-weight:600;color:#fff}.held-number{font-size:13px;font-weight:500;color:#fff}.held-actions{display:flex;gap:8px;align-items:center}.held-btn{padding:6px 16px;border-radius:20px;border:none;font-size:13px;font-weight:600;cursor:pointer;transition:transform .2s,box-shadow .2s}.held-btn:hover{transform:scale(1.05);box-shadow:0 4px 12px #0003}.swap-btn{background:#3b82f6;color:#fff}.merge-btn{background:#10b981;color:#fff}.h-77px{height:77px}.incoming-banners-container{width:100%;padding:5px 8px;height:100%;gap:8px;overflow-y:auto}.call-container-model{width:385px!important;height:646px!important;margin:auto 0 0 1px;border-radius:20px;box-shadow:6px 6px 10px -1px #00000026,-5px -4px 10px -1px #00000026;display:flex;box-sizing:border-box;position:relative;overflow:hidden;justify-content:center;align-items:center}.incoming-banner{top:0;left:0;width:100%;right:0;background:linear-gradient(135deg,#1e3a8a 0%,#3b82f6 100%);padding:12px 16px;z-index:2000;box-shadow:0 4px 12px #0003;border-radius:16px}.incoming-banner-content{display:flex;align-items:center;justify-content:space-between;gap:12px}.incoming-info{flex:1;display:flex;flex-direction:column;gap:4px}.incoming-label{font-size:11px;color:#fffc;text-transform:uppercase;letter-spacing:.5px}.incoming-caller{display:flex;flex-direction:column;gap:2px}.caller-name{font-size:15px;font-weight:600;color:#fff}.caller-number{font-size:13px;color:#ffffffe6}.incoming-actions{display:flex;gap:8px;align-items:center}.banner-btn{width:44px;height:44px;border-radius:50%;border:none;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:transform .2s}.banner-btn:hover{transform:scale(1.1)}.banner-btn .material-symbols-outlined{font-size:20px}.accept-btn{background:#10b981}.accept-btn .material-symbols-outlined{color:#fff}.reject-btn{background:#ef4444}.reject-btn .material-symbols-outlined{color:#fff}.contacts-panel{position:absolute;top:0;bottom:12px;width:340px;background:#ffffff;border-radius:16px;box-shadow:0 10px 25px #00000026;display:flex;flex-direction:column;overflow:hidden;height:40.4rem;left:24.1rem;z-index:1000000}.contacts-header{height:56px;display:flex;align-items:center;justify-content:space-between;padding:0 16px;border-bottom:1px solid #f0f0f0}.contacts-header .title{font-weight:600}.contacts-header .back,.contacts-header .search{color:#9aa0a6;cursor:pointer}.disabled{opacity:.5;pointer-events:none}.contacts-list{padding:8px 8px 12px;overflow-y:auto}.contact-item{display:flex;align-items:center;padding:10px 8px;border-radius:10px}.contact-item:hover{background:#f7f9fc}.contact-avatar{width:37px;height:37px;border-radius:50%;object-fit:cover;margin-right:12px}.contact-info{flex:1}.contact-name{font-weight:600;color:#111827}.contact-title{font-size:12px;color:#6b7280}.contact-call-btn{display:inline-flex;align-items:center;gap:6px;background:#234de8;color:#fff;border:none;border-radius:16px;padding:8px;cursor:pointer}.contact-add-btn{background-color:#2ecc71!important}.conference-hold-contact{display:inline-flex;align-items:center;gap:5px;background:#727070;color:#fff;border:none;border-radius:50%;padding:7px;cursor:pointer}.conference-hold-contact.on-hold{background:#28a745!important;color:#fff}.user-info-section{width:100%;height:100%;overflow-y:auto;overflow-x:hidden!important}.user-info-section::-webkit-scrollbar{display:none}.toggle-btn{cursor:pointer}.text-container{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;transition:all .3s ease}.text-container.expanded{-webkit-line-clamp:unset}.userName{font-family:FontAwesome}.subject-text{display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden}.conference-contact{display:inline-flex;align-items:center;gap:5px;background:#e14e4e;color:#fff;border:none;border-radius:50%;padding:7px;cursor:pointer}.organizer-label{padding:1px 5px;font-size:11px;border-radius:10px;border:1px solid #a0a0a0;margin-top:2px;background:#fcfcfc}.custom-modal{position:absolute;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.5);display:flex;justify-content:center;align-items:center;z-index:1000;border-radius:21px}.modal-content{background:#ffffff;padding:25px;border-radius:8px;width:350px;text-align:center}.title{margin-bottom:15px;color:#d9534f}.message{margin-bottom:20px}.button-group{display:flex;justify-content:space-between}.btn{padding:8px 15px;border:none;border-radius:5px;cursor:pointer;font-weight:500}.end-btn{background-color:#dc3545;color:#fff;display:flex;align-items:center;font-size:13px}.leave-btn{background-color:#007bff;color:#fff}.contact-call-btn .material-symbols-outlined{font-size:18px;color:#fff}.contact-call-btn .label{font-size:12px}.parallax>use{animation:move-forever 25s cubic-bezier(.55,.5,.45,.5) infinite}.parallax>use:nth-child(1){animation-delay:-2s;animation-duration:7s}.parallax>use:nth-child(2){animation-delay:-3s;animation-duration:10s}.parallax>use:nth-child(3){animation-delay:-4s;animation-duration:13s}.parallax>use:nth-child(4){animation-delay:-5s;animation-duration:20s}@keyframes move-forever{0%{transform:translate3d(-90px,0,0)}to{transform:translate3d(85px,0,0)}}.animated-margin{transition:margin-top .5s ease}app-incoming-call{position:absolute;top:0;left:0;width:100%;height:100%;background-color:transparent;z-index:1001}.min-call-container{width:320px;height:124px;border-radius:20px;box-shadow:6px 6px 10px -1px #00000026,-5px -4px 10px -1px #00000026;display:flex;flex-direction:column;box-sizing:border-box;position:relative;overflow:hidden;margin:auto;align-items:center;padding:12px 16px;color:#fff}.min-call-animation{background:#fff;width:48px;height:48px;position:relative;margin:0 12px 0 auto;border-radius:100%;border:solid 2px #fff}.min-avatar-img{width:46px;height:46px;border-radius:100%;position:absolute;left:0;top:0}.min-callerDetails{color:#fff;display:flex;flex-direction:column;align-items:flex-start}.name{width:170px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:20px;margin:0;color:#fff}.min-callerDetails p{margin:0;color:#fff}.min-btn-container{position:relative;display:flex;width:100%;justify-content:flex-start;align-items:center;margin-top:6px}.min-call-sec-btn{width:40px;height:40px;box-sizing:border-box;border:1px solid #cccbcb;background-color:transparent;border-radius:20px;display:flex;align-items:center;justify-content:center;margin-right:12px;box-shadow:6px 6px 10px -1px #bebebe26,-5px -4px 10px -1px #d2d2d226}.min-call-sec-btn span{color:#cccbcb}.min-call-btn{width:40px;height:40px;border-radius:20px;box-sizing:border-box;border:2px solid white;display:flex;align-items:center;justify-content:center}.fullscreen{position:absolute;right:18px;top:14px;color:#e8e8e8;font-size:18px;cursor:pointer}.btn-container{display:flex;flex-wrap:wrap;padding:0 24px}.dial-btn{width:40px;height:40px;background-color:transparent;text-align:center;box-sizing:border-box;margin:4px 25px;font-size:24px;display:flex;flex-direction:column;justify-content:center;align-items:center;font-family:Lato,sans-serif;font-weight:900;font-style:normal;color:#b5b5b5;cursor:pointer}.btn-albhabets{font-family:Lato,sans-serif;font-size:12px;font-weight:400}.min-timer{width:50px;font-size:18px;margin-right:10px;border-radius:4px;height:35px;display:flex;align-items:center}.record-action-btns{display:flex;flex-direction:column;align-items:center;margin-top:35px}.record-btn-container{position:relative}.record-btn{border:none;border-radius:50%;width:50px;height:50px;display:flex;align-items:center;justify-content:center;cursor:pointer;margin:0 5px;position:relative;overflow:hidden}.record-btn.start-stop .recording-icon{width:50%;height:50%;border-radius:50%;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}.record-btn.start-stop.recording .recording-icon{background-color:#000}.record-btn.start-stop.recording{border:3px solid #000}.record-btn.start-stop.stopped .recording-icon{background-color:red;border:3px solid #ff0000;border-radius:50%;position:absolute}.record-btn.start-stop.stopped{border:3px solid #ff0000}.record-btn.start-stop.stopped .recording-icon{width:40%;height:40%;border-radius:0;background-color:red}.pause-resume-btns{display:flex;flex-direction:column;align-items:center;margin-top:10px}.record-btn.pause-resume{border:none;border-radius:50%;width:50px;height:50px;background:white;display:flex;align-items:center;justify-content:center;margin:5px 0}.record-btn.pause-resume .material-symbols-outlined{font-size:20px;color:#000}.timer-display{font-size:1.2em;margin-top:10px;color:#000}.w-40{width:40%}.w-60{width:60%}.callToNum{color:#fff;font-weight:400;text-align:center}.callToNum span{font-weight:600}.conference-call-view{display:flex;flex-direction:column;align-items:center;justify-content:flex-start;width:100%;padding:12px 16px 35px;color:#fff;height:100%}.conf-heading{display:flex;align-items:center;gap:8px;margin-top:8px}.conf-icon{color:#4579aa;font-size:32px;width:50px;height:50px;border:1px solid gray;border-radius:50%;display:flex;align-items:center;justify-content:center;background:#e1e1e1}.conf-title{font-weight:600;font-size:20px}.conf-name{margin-top:10px;font-size:17px;font-weight:600;text-align:center}.conf-timer{margin-top:4px;font-size:12px;opacity:.9}.conf-record{margin-top:14px}.record-stop-btn{width:44px;height:44px;border-radius:50%;border:none;background:#fff;display:flex;align-items:center;justify-content:center}.record-stop-btn .material-symbols-outlined{color:#e14e4e;font-size:28px}.conf-remove{margin-top:8px}.remove-btn{background:#ff0000!important;color:#fff;border:none;border-radius:6px;padding:6px 12px;font-size:12px;width:82px!important;height:auto}.conf-actions{margin-top:14px;display:flex;align-items:center;justify-content:center;gap:18px}.circle-btn{width:56px;height:56px;border-radius:50%;border:none;background:#000;display:flex;align-items:center;justify-content:center}.circle-btn .material-symbols-outlined{color:#fff;font-size:24px}.circle-btn.active{opacity:.85}.conf-end{margin-top:16px}.circle-btn.danger{background:#e14e4e}.circle-btn.danger .material-symbols-outlined{color:#fff}\n"] }]
|
|
3591
3226
|
}], ctorParameters: function () { return [{ type: ExtensionService }, { type: i0.ChangeDetectorRef }, { type: TwilioService }, { type: IpAddressService }, { type: IncomeingCallSocketService }]; }, propDecorators: { callData: [{
|
|
3592
3227
|
type: Input
|
|
3593
3228
|
}], selectedCallerId: [{
|
|
@@ -3730,69 +3365,8 @@ class DialboxComponent {
|
|
|
3730
3365
|
this.isLoadershow = false;
|
|
3731
3366
|
this.isIncomingCallnotification = false;
|
|
3732
3367
|
this.notificationCallList = [];
|
|
3733
|
-
this.
|
|
3734
|
-
|
|
3735
|
-
"conferenceName": "conf_6953850f1522800c4f3cc715",
|
|
3736
|
-
"conferenceId": "6953850f1522800c4f3cc715",
|
|
3737
|
-
"conferenceStatus": "completed",
|
|
3738
|
-
"isActive": false,
|
|
3739
|
-
"conferenceSid": "CFa38eab13863a6af9827b348120e369b8",
|
|
3740
|
-
"participants": [
|
|
3741
|
-
{
|
|
3742
|
-
"callDuration": 88,
|
|
3743
|
-
"callSid": "CA48abba51da47c32749ba568d7f4eccca",
|
|
3744
|
-
"role": "callee",
|
|
3745
|
-
"joinedAt": "Tue Dec 30 07:53:54 UTC 2025",
|
|
3746
|
-
"isHold": false,
|
|
3747
|
-
"isConference": true,
|
|
3748
|
-
"userId": "69392c670665b958db876888",
|
|
3749
|
-
"forwardedTo": "",
|
|
3750
|
-
"leftAt": "Tue Dec 30 07:55:25 UTC 2025",
|
|
3751
|
-
"duration": 2,
|
|
3752
|
-
"isLeft": true,
|
|
3753
|
-
"conferenceId": "6953850f1522800c4f3cc715",
|
|
3754
|
-
"from": "+12252519886",
|
|
3755
|
-
"to": "+916353645844",
|
|
3756
|
-
"status": "completed",
|
|
3757
|
-
"direction": "outgoing-call"
|
|
3758
|
-
},
|
|
3759
|
-
{
|
|
3760
|
-
"callDuration": 65,
|
|
3761
|
-
"callSid": "CAcbc286a9e6559f1a3f1b51f48ce3f73b",
|
|
3762
|
-
"role": "callee",
|
|
3763
|
-
"joinedAt": "Tue Dec 30 07:54:14 UTC 2025",
|
|
3764
|
-
"isHold": false,
|
|
3765
|
-
"isConference": true,
|
|
3766
|
-
"userId": "69392c670665b958db876888",
|
|
3767
|
-
"forwardedTo": "",
|
|
3768
|
-
"leftAt": "Tue Dec 30 07:55:25 UTC 2025",
|
|
3769
|
-
"duration": 2,
|
|
3770
|
-
"isLeft": true,
|
|
3771
|
-
"conferenceId": "6953850f1522800c4f3cc715",
|
|
3772
|
-
"toName": "Test ",
|
|
3773
|
-
"fromName": "Test ",
|
|
3774
|
-
"from": "+12252519886",
|
|
3775
|
-
"to": "+916354564733",
|
|
3776
|
-
"status": "completed",
|
|
3777
|
-
"direction": "outgoing-call"
|
|
3778
|
-
},
|
|
3779
|
-
{
|
|
3780
|
-
"callDuration": 25,
|
|
3781
|
-
"callSid": "CA2fb6b893cf406c033311e3b11d6e760f",
|
|
3782
|
-
"joinedAt": "Tue Dec 30 07:55:06 UTC 2025",
|
|
3783
|
-
"isHold": false,
|
|
3784
|
-
"isConference": true,
|
|
3785
|
-
"forwardedTo": "",
|
|
3786
|
-
"duration": 1,
|
|
3787
|
-
"isLeft": true,
|
|
3788
|
-
"conferenceId": "6953850f1522800c4f3cc715",
|
|
3789
|
-
"from": "+16098065088",
|
|
3790
|
-
"to": "+12252302470",
|
|
3791
|
-
"status": "no-answer",
|
|
3792
|
-
"direction": "incoming-call"
|
|
3793
|
-
}
|
|
3794
|
-
]
|
|
3795
|
-
};
|
|
3368
|
+
this.deviceNumberList = [];
|
|
3369
|
+
this.conferenceCallInfo = {};
|
|
3796
3370
|
this.closeDialpadEvent = new EventEmitter();
|
|
3797
3371
|
this.callInitiated = new EventEmitter();
|
|
3798
3372
|
this.endCallEvent = new EventEmitter();
|
|
@@ -3873,14 +3447,22 @@ class DialboxComponent {
|
|
|
3873
3447
|
this.incomeingCallSocketService.listen().subscribe(async (incomingCallData) => {
|
|
3874
3448
|
this.twilioService.conferenceCallInfo = incomingCallData;
|
|
3875
3449
|
incomingCallData = incomingCallData?.length > 0 ? incomingCallData.filter((item) => item.participants?.length > 0) : [];
|
|
3876
|
-
|
|
3450
|
+
let updatedConferenceCallData = [];
|
|
3451
|
+
incomingCallData.forEach((callInfo, i) => {
|
|
3452
|
+
let ourNumber = {};
|
|
3453
|
+
ourNumber = callInfo.participants.find((resData) => ((this.deviceNumberList.includes(resData?.from) && resData?.to == 'c2c_softphone_client') || (this.deviceNumberList.includes(resData?.to) && resData?.direction == 'incoming-call')) && !resData?.isLeft);
|
|
3454
|
+
if (ourNumber?.id) {
|
|
3455
|
+
updatedConferenceCallData.push(callInfo);
|
|
3456
|
+
}
|
|
3457
|
+
});
|
|
3458
|
+
if (!!updatedConferenceCallData?.length) {
|
|
3877
3459
|
// this.incomingCallsList = incomingCallData.participants.filter((item: any) => !item.isLeft) || [];
|
|
3878
|
-
this.incomingCallsList =
|
|
3460
|
+
this.incomingCallsList = updatedConferenceCallData || [];
|
|
3879
3461
|
let parentCall = [];
|
|
3880
3462
|
if (this.notificationCallList?.length) {
|
|
3881
3463
|
this.notificationCallList = this.notificationCallList.filter((res) => res.endTime >= (new Date().getTime()));
|
|
3882
3464
|
this.notificationCallList.forEach((call) => {
|
|
3883
|
-
|
|
3465
|
+
updatedConferenceCallData.forEach((item) => {
|
|
3884
3466
|
let info = item.participants.find((resInfo) => resInfo?.id === call?.participantId);
|
|
3885
3467
|
// return info?.id
|
|
3886
3468
|
if (info) {
|
|
@@ -4267,8 +3849,10 @@ class DialboxComponent {
|
|
|
4267
3849
|
isIncomingCall: true,
|
|
4268
3850
|
participantId: this.incomingCallnotification.data.data?.participantId,
|
|
4269
3851
|
participants: [
|
|
4270
|
-
{
|
|
4271
|
-
|
|
3852
|
+
{
|
|
3853
|
+
direction: "incoming-call", businessNumber: this.incomingCallnotification.data.data?.c2cBusiness == 'true' ? true : false, img: this.incomingCallnotification.data.data?.fromImage || this.incomingCallnotification.data.data?.image || 'assets/images/user.jpg', isIncomingCall: true, isHold: false, isConference: false, isAcceptCall: false, dial: true, phone: this.incomingCallnotification.data.data?.fromNumber, to: this.incomingCallnotification.data.data?.toNumber,
|
|
3854
|
+
from: this.incomingCallnotification.data.data?.fromNumber, fromName: this.incomingCallnotification.data.data?.fromName, participantId: this.incomingCallnotification.data.data?.participantId, name: this.incomingCallnotification.data.data?.fromName, time: '', id: this.incomingCallnotification.data.data?.participantId, conferenceId: this.incomingCallnotification?.data?.data?.conferenceId
|
|
3855
|
+
}
|
|
4272
3856
|
],
|
|
4273
3857
|
};
|
|
4274
3858
|
this.notificationCallList = await this.notificationCallList.filter((res) => res?.endTime > (new Date().getTime()));
|
|
@@ -4381,6 +3965,7 @@ class DialboxComponent {
|
|
|
4381
3965
|
//this.callerIdList = res.callerIdList.filter(item => item.type === "C2C Softphone Number");
|
|
4382
3966
|
this.callerIdList = res.callerIdList.filter((item) => item.voiceFeature === true);
|
|
4383
3967
|
// this.callerIdList = res.callerIdList;
|
|
3968
|
+
this.deviceNumberList = this.callerIdList.map((res) => res.number);
|
|
4384
3969
|
if (this.callerIdList.length == 1) {
|
|
4385
3970
|
this.selectedCallerId = this.callerIdList[0];
|
|
4386
3971
|
}
|