diff --git a/app/utils/icons.js b/app/utils/icons.js index ace2b13c..6c678fe0 100644 --- a/app/utils/icons.js +++ b/app/utils/icons.js @@ -79,6 +79,8 @@ Ext.define('Ngcp.csc.icons', { users: "x-fa fa-users", user_secret: "x-fa fa-user-secret", video: "x-fa fa-video-camera", - video2x: "x-fa fa-video-camera fa-2x" + video2x: "x-fa fa-video-camera fa-2x", + close: "x-fa fa-times", + close2x: "x-fa fa-times fa-2x" } }) diff --git a/app/utils/locales.js b/app/utils/locales.js index f85083c5..ba78edfc 100644 --- a/app/utils/locales.js +++ b/app/utils/locales.js @@ -1654,6 +1654,27 @@ Ext.define('Ngcp.csc.locales', { it: 'Incoming {0} call from', fr: 'Incoming {0} call from', sp: 'Incoming {0} call from' + }, + close: { + en: 'Close', + it: 'Close', + de: 'Close', + fr: 'Close', + sp: 'Close' + }, + call_aborted_by: { + en: 'Call aborted by {0}', + it: 'Call aborted by {0}', + de: 'Call aborted by {0}', + fr: 'Call aborted by {0}', + sp: 'Call aborted by {0}' + }, + abort_reason: { + en: 'Reason: {0}', + it: 'Reason: {0}', + de: 'Reason: {0}', + fr: 'Reason: {0}', + sp: 'Reason: {0}' } }, faxsend: { diff --git a/classic/sass/src/view/common/rtc/RtcPanel.scss b/classic/sass/src/view/common/rtc/RtcPanel.scss index 9cd1ac50..12cf9d1a 100644 --- a/classic/sass/src/view/common/rtc/RtcPanel.scss +++ b/classic/sass/src/view/common/rtc/RtcPanel.scss @@ -60,45 +60,8 @@ $border-radius : 50%; } } -.rtc-decline-call { - background: red !important; - border-color: #db0404 !important; - &:after { - font-family: FontAwesome; - content: "\f05e"; - padding-left: 18px; - color: #F1F1F1; - position: relative; - top: -18px; - } -} - -.rtc-decline-call-pressed { - background: #db0404 !important; - border-color: #db0404 !important; -} - -.rtc-incoming-label, -.rtc-incoming-number { - margin: 0 auto; -} - -.rtc-incoming-label, -.rtc-outgoing-label { - font-size: 16px; - .x-autocontainer-innerCt { - font-size: 16px; - } -} - -.rtc-incoming-number { - .x-autocontainer-innerCt { - font-size: 24px; - } -} - -.rtc-button-margin { - margin: 0 50px 0 0; +.call-button * { + font-size: 22px; } .call-button { @@ -106,27 +69,23 @@ $border-radius : 50%; background-color: #16b603; color: white; border-width: 0; + .icon-small { + font-size: 11px; + position: absolute; + top: 2px; + right: 3px; + } + .icon-large { + font-size: 22px; + position: absolute; + bottom: 0px; + left: 2px; + } } -.call-button * { - font-size: 22px; -} - -.call-button .icon-large { - font-size: 22px; - position: absolute; - bottom: 0px; - left: 2px; -} - -.call-button .icon-small { - font-size: 11px; - position: absolute; - top: 2px; - right: 3px; -} -.call-button-cancel { +.call-button-cancel, +.call-button-close { background-color: red; } @@ -134,21 +93,33 @@ $border-radius : 50%; background-color: forestgreen; } -.call-icon-cancel { +.call-icon-cancel, +.call-icon-close { position: absolute; - transform: rotate(135deg); font-size: 22px; +} + +.call-icon-cancel { + transform: rotate(135deg); top: 2px; left: 4px; } -.call-button-cancel.x-btn.x-btn-pressed, +.call-icon-close { + top: 0px; + left: 5px; +} + +.call-button-close .x-btn .x-btn-pressed, +.call-button-close-focus, +.call-button-close-over, +.call-button-cancel .x-btn .x-btn-pressed, .call-button-cancel-focus, .call-button-cancel-over { background-color: darkred; } -.call-button-accept.x-btn.x-btn-pressed, +.call-button-accept .x-btn .x-btn-pressed, .call-button-accept-focus, .call-button-accept-over { background-color: darkgreen; diff --git a/classic/src/view/common/rtc/CallPanel.js b/classic/src/view/common/rtc/CallPanel.js index 66333d1e..8422613b 100644 --- a/classic/src/view/common/rtc/CallPanel.js +++ b/classic/src/view/common/rtc/CallPanel.js @@ -1,95 +1,146 @@ - Ext.define('NgcpCsc.view.common.rtc.CallPanel', { extend: 'Ext.form.Panel', alias: 'widget.call-panel', padding: '60 0 0 0', bind: { - hidden: '{!callEnabled}' + hidden: '{!callPanelEnabled}' }, items: [{ - layout : { - type : 'vbox', - align : 'center', - pack: 'center', - - }, - bind: { - hidden: '{!outgoingCall}' - }, - items: [ - { - bind: { - text: '{callActionLabel}' - }, - xtype: 'label', - margin: '0 0 20 0' + layout: { + type: 'vbox', + align: 'center', + pack: 'center' }, - { - bind: { - text: '{numberToCall}' + bind: { + hidden: '{!outgoingCall}' + }, + items: [{ + bind: { + html: '{callActionLabel}' + Ngcp.csc.animations.loading_dots + }, + xtype: 'label' }, - xtype: 'label', - margin: '0 0 20 0', - userCls: 'call-number-label', + { + bind: { + text: '{numberToCall}' + }, + xtype: 'label', + margin: '0 0 20 0', + userCls: 'call-number-label' + }, + { + xtype: 'button', + userCls: 'call-button call-button-cancel call-button-hangup', + overCls: 'call-button-cancel-over', + focusCls: 'call-button-cancel-focus', + width: 40, + height: 40, + html: '', + listeners: { + click: 'cancelOutgoingCall' + } + } + ] + }, { + bind: { + hidden: '{!callAborted}' + }, + layout: { + type: 'vbox', + align: 'center', + pack: 'center' }, - { - xtype: 'button', - text: '', - userCls: 'call-button call-button-cancel call-button-hangup', - overCls: 'call-button-cancel-over', - focusCls: 'call-button-cancel-focus', - width: 40, - height: 40, - html: '', - listeners: { - click: 'cancelOutgoingCall' + items: [{ + bind: { + text: Ext.String.format(Ngcp.csc.locales.rtc.call_aborted_by[localStorage.getItem('languageSelected')], '{incomingCaller}') + }, + xtype: 'label', + margin: '0 0 20 0' + }, { + bind: { + text: Ext.String.format(Ngcp.csc.locales.rtc.abort_reason[localStorage.getItem('languageSelected')], '{abortReason}') + }, + xtype: 'label', + margin: '0 0 20 0' + }, + { + xtype: 'button', + userCls: 'call-button call-button-close', + overCls: 'call-button-close-over', + focusCls: 'call-button-close-focus', + width: 40, + height: 40, + html: '', + listeners: { + click: 'hideAbortedState' + } } - } - ]}, + ] + }, { + layout: { + type: 'vbox', + align: 'center', + pack: 'center' + + }, bind: { hidden: '{!incomingCallPending}' }, items: [{ - userCls: 'rtc-incoming-label', - height: 50, bind: { html: Ext.String.format(Ngcp.csc.locales.rtc.incoming_call_from[localStorage.getItem('languageSelected')] + Ngcp.csc.animations.loading_dots, '{incomingType}') - } + }, + xtype: 'label' }, { - userCls: 'rtc-incoming-number', - height: 40, bind: { - html: '{incomingCaller}' - } - }, { - xtype: 'button', - iconCls: Ngcp.csc.icons.phone2x, - width: 50, - height: 50, - userCls: 'rtc-button-margin', - listeners: { - click: 'acceptCallAudio' - } - }, { - xtype: 'button', - iconCls: Ngcp.csc.icons.video2x, - width: 50, - height: 50, - userCls: 'rtc-button-margin', - listeners: { - click: 'acceptCallVideo' - } + text: '{incomingCaller}' + }, + xtype: 'label', + margin: '0 0 20 0', + userCls: 'call-number-label' }, { - xtype: 'button', - iconCls: Ngcp.csc.icons.phone_cancel2x, - userCls: 'rtc-decline-call', - pressedCls: 'rtc-decline-call-pressed', - width: 50, - height: 50, - listeners: { - click: 'declineCall' - } + layout: { + type: 'hbox', + align: 'center', + pack: 'center' + }, + items: [{ + xtype: 'button', + margin: '0 10 0 0', + userCls: 'call-button call-button-accept', + overCls: 'call-button-accept-over', + focusCls: 'call-button-accept-focus', + width: 40, + height: 40, + html: '', + listeners: { + click: 'acceptCallAudio' + } + }, { + xtype: 'button', + margin: '0 10 0 0', + userCls: 'call-button call-button-accept', + overCls: 'call-button-accept-over', + focusCls: 'call-button-accept-focus', + width: 40, + height: 40, + html: '', + listeners: { + click: 'acceptCallVideo' + } + }, { + xtype: 'button', + userCls: 'call-button call-button-cancel call-button-hangup', + overCls: 'call-button-cancel-over', + focusCls: 'call-button-cancel-focus', + width: 40, + height: 40, + html: '', + listeners: { + click: 'declineCall' + } + }] }] } ] diff --git a/classic/src/view/common/rtc/RtcController.js b/classic/src/view/common/rtc/RtcController.js index d76d3a28..dfb03f4a 100644 --- a/classic/src/view/common/rtc/RtcController.js +++ b/classic/src/view/common/rtc/RtcController.js @@ -27,13 +27,11 @@ Ext.define('NgcpCsc.view.common.rtc.RtcController', { }, initCall: function(mediaType) { - var $ct = this; var $vm = this.getViewModel(); var callee = $vm.get('numberToCall'); var network = $vm.get('rtcEngineNetwork'); var localMediaStream = $vm.get('rtcEngineLocalMediaStream'); - if (callee !== '' && callee !== null && callee !== void(0)) { if(localMediaStream !== null) { localMediaStream.stop(); @@ -234,9 +232,7 @@ Ext.define('NgcpCsc.view.common.rtc.RtcController', { me.stopRingSound(); vm.set('callPanelEnabled', true); vm.set('micEnabled', true); - me.startMedia(audioOn, videoOn); - me.intervalId = setInterval(function() { seconds++; if (seconds == 60) { @@ -452,10 +448,16 @@ Ext.define('NgcpCsc.view.common.rtc.RtcController', { rtcNetwork.onConnect(function() { $vm.set('callPanelEnabled', true); }).onIncomingCall(function(call) { - $ct.incomingCallPending(); - call.onRemoteMedia(function(stream){ $ct.incomingRemoteMedia(stream); }) + $ct.incomingCallPending(call); + call.onRemoteMedia(function(stream){ + $vm.set('rtcEngineRemoteMediaStream', stream); + $ct.incomingRemoteMedia(stream); + }) + // XXX @hherzog Should these both be invoking the same function? + // I separated them for now, as they were causing double invoking + // of incomingRemoteMediaEnded() .onRemoteMediaEnded(function(){ $ct.incomingRemoteMediaEnded(); }) - .onEnded(function(){ $ct.incomingRemoteMediaEnded() }); + .onEnded(function(reason){ $ct.incomingCallEnded(reason) }); }).onDisconnect(function(){ $vm.set('callPanelEnabled', false); $vm.set('callDisabledReason', rtcNetwork.disconnectReason); @@ -503,10 +505,12 @@ Ext.define('NgcpCsc.view.common.rtc.RtcController', { this.callEnded(); }, - incomingCallPending: function() { - this.getView().show().expand(); - this.showIncomingCallPendingState(); + incomingCallPending: function(call) { console.log('incomingCallPending'); + var peerNum = call.peer.split(/(:|@)/)[2]; + var type = call.type == 'call' ? 'audio' : call.type; + this.getView().show().expand(); + this.showIncomingCallPendingState(peerNum, type); }, incomingRemoteMedia: function(stream) { @@ -517,6 +521,11 @@ Ext.define('NgcpCsc.view.common.rtc.RtcController', { console.log('incomingRemoteMediaEnded'); }, + incomingCallEnded: function (reason) { + this.hideIncomingCallPendingState(); + this.showAbortedState(reason); + }, + incomingEnded: function() { console.log('incomingEnded'); this.callEnded(); @@ -535,7 +544,7 @@ Ext.define('NgcpCsc.view.common.rtc.RtcController', { this.getViewModel().set('callRinging', false); this.stopRingSound(); if(call !== null) { - call.end(); + call.end('declined'); } if(mediaStream !== null) { mediaStream.stop(); @@ -555,10 +564,23 @@ Ext.define('NgcpCsc.view.common.rtc.RtcController', { this.playRingSound(); }, - // parameter state true causes the class for the background color change to - // be added, and parameter state false causes the class to be removed + showAbortedState: function (reason) { + var $vm = this.getViewModel(); + $vm.set('abortReason', reason || 'declined'); + $vm.set('phoneComposerHidden', true); + $vm.set('callAborted', true); + }, + + hideAbortedState: function () { + var $vm = this.getViewModel(); + $vm.set('abortReason', ''); + $vm.set('callAborted', false); + $vm.set('incomingCaller', ''); + this.closeRtcPanel(); + }, + setRtcpanelTitleColor: function (state) { - // parameter true to change color, and false to revert + // parameters: true to change color, and false to revert var rtcpanel = Ext.getCmp('rtcpanel'); rtcpanel.toggleCls('rtc-title-call-initiation', state); }, @@ -576,20 +598,22 @@ Ext.define('NgcpCsc.view.common.rtc.RtcController', { sound.currentTime = 0; }, - showIncomingCallPendingState: function () { - // @hherzog: I added parameters for caller number and media type for - // now, but they can be replaced with cdk method calls in variable - // declaration below if you prefer - var vm = this.getViewModel(); - var caller = '+4312345'; - var type = 'audio'; - vm.set('callPanel', true); - vm.set('incomingCallPending', true); - vm.set('phoneComposerHidden', true); - vm.set('title', Ngcp.csc.locales.rtc.incoming_call[localStorage.getItem('languageSelected')]); - vm.set('incomingCaller', caller); - vm.set('incomingType', type); - vm.set('incomingCallHidden', false); + closeRtcPanel: function () { + var rtcpanel = Ext.getCmp('rtcpanel'); + if (rtcpanel) { + rtcpanel.close(); + }; + }, + + showIncomingCallPendingState: function (caller, type) { + var $vm = this.getViewModel(); + $vm.set('callPanel', true); + $vm.set('incomingCallPending', true); + $vm.set('phoneComposerHidden', true); + $vm.set('title', Ngcp.csc.locales.rtc.incoming_call[localStorage.getItem('languageSelected')]); + $vm.set('incomingCaller', caller); + $vm.set('incomingType', type); + $vm.set('incomingCallHidden', false); this.setRtcpanelTitleColor(true); }, @@ -600,11 +624,8 @@ Ext.define('NgcpCsc.view.common.rtc.RtcController', { vm.set('callPanel', false); vm.set('incomingCallPending', false); vm.set('title', ''); - vm.set('incomingCaller', ''); vm.set('incomingType', ''); - if (rtcpanel) { // Closes rtcpanel - rtcpanel.close(); - }; + this.setRtcpanelTitleColor(false); }, declineCall: function () { diff --git a/classic/src/view/common/rtc/RtcModel.js b/classic/src/view/common/rtc/RtcModel.js index cfc2d58e..b2c0a123 100644 --- a/classic/src/view/common/rtc/RtcModel.js +++ b/classic/src/view/common/rtc/RtcModel.js @@ -31,6 +31,7 @@ Ext.define('NgcpCsc.view.rtc.RtcModel', { // panel status minimized: true, rtcEngineLocalMediaStream: null, + rtcEngineRemoteMediaStream: null, rtcEngineCall: null, rtcEngineNetwork: null, rtcEngineClient: null, @@ -42,7 +43,9 @@ Ext.define('NgcpCsc.view.rtc.RtcModel', { outgoingCallPending: false, incomingCallPending: false, incomingType: '', - incomingCaller: '' + incomingCaller: '', + callAborted: false, + abortReason: '' }, formulas: { disableSubmit: function(get) { diff --git a/classic/src/view/common/rtc/composer/Phone.js b/classic/src/view/common/rtc/composer/Phone.js index 67618792..7b853d06 100644 --- a/classic/src/view/common/rtc/composer/Phone.js +++ b/classic/src/view/common/rtc/composer/Phone.js @@ -35,7 +35,6 @@ Ext.define('NgcpCsc.view.common.rtc.composer.Phone', { xtype: 'container', items: [{ xtype: 'button', - text: '', margin: '0 10 0 0', listeners: { click: 'sendAudio' @@ -48,7 +47,6 @@ Ext.define('NgcpCsc.view.common.rtc.composer.Phone', { html: '' }, { xtype: 'button', - text: '', listeners: { click: 'sendVideo' }, diff --git a/classic/src/view/main/MainController.js b/classic/src/view/main/MainController.js index 2f1000b9..f8ebb457 100644 --- a/classic/src/view/main/MainController.js +++ b/classic/src/view/main/MainController.js @@ -311,7 +311,7 @@ Ext.define('NgcpCsc.view.main.MainController', { }); // override pseudo element (can also be done using http://docs.sencha.com/extjs/6.2.0/classic/Ext.util.CSS.html#method-createStyleSheet) - if (document.styleSheets[0]) { + if (document.styleSheets[0] && document.styleSheets[0].addRule) { document.styleSheets[0].addRule('.x-treelist-item-icon::before', 'line-height:' + currentItemsHeight + 'px !important'); document.styleSheets[0].addRule('.x-treelist-item-tool:after', 'height:' + currentItemsHeight + 'px !important'); document.styleSheets[0].addRule('.x-treelist-item-tool::before', 'line-height:' + currentItemsHeight + 'px !important'); diff --git a/classic/src/view/pages/callforward/CallForwardController.js b/classic/src/view/pages/callforward/CallForwardController.js index e7089cb3..25a68fa0 100644 --- a/classic/src/view/pages/callforward/CallForwardController.js +++ b/classic/src/view/pages/callforward/CallForwardController.js @@ -17,7 +17,7 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardController', { cfSourcesetStoreLoaded: 'cfSourcesetStoreLoaded', cfStoreBeforeSync: 'cfStoreBeforeSync', cfSourcesetBeforeSync: 'cfSourcesetBeforeSync', - cfTimesetBeforeSync: 'cfTimesetBeforeSync', + cfTimesetBeforeSync: 'cfTimesetBeforeSync' } } }, diff --git a/sass/var/all.scss b/sass/var/all.scss index 4f002620..0063fc42 100644 --- a/sass/var/all.scss +++ b/sass/var/all.scss @@ -109,3 +109,4 @@ $user: "\f007"; $users: "\f0c0"; $user-secret: "\f21b"; $video: "\f03d"; +$close: "\f00d";