diff --git a/.gitignore b/.gitignore index a964c5e2..729e9811 100644 --- a/.gitignore +++ b/.gitignore @@ -18,5 +18,4 @@ npm-debug.log t/*.xml sass/example/fashion.html sass/example/render.js -rtc/ sencha-error-*.log diff --git a/app/utils/animations.js b/app/utils/animations.js new file mode 100644 index 00000000..9cda26ed --- /dev/null +++ b/app/utils/animations.js @@ -0,0 +1,5 @@ +Ext.define('Ngcp.csc.animations', { + statics: { + loading_dots: '
...
' + } +}) diff --git a/app/utils/icons.js b/app/utils/icons.js index 49c5102b..ace2b13c 100644 --- a/app/utils/icons.js +++ b/app/utils/icons.js @@ -58,6 +58,8 @@ Ext.define('Ngcp.csc.icons', { phone: "x-fa fa-phone", phone2x: "x-fa fa-phone fa-2x", phone3x: "x-fa fa-phone fa-3x", + phone_cancel: "x-fa fa-phone fa-rotate-180", + phone_cancel2x: "x-fa fa-phone fa-rotate-90 fa-2x", phonesquare: "x-fa fa-phone-square", send: "x-fa fa-send", send2x: "x-fa fa-send fa-2x", @@ -76,6 +78,7 @@ Ext.define('Ngcp.csc.icons', { user: "x-fa fa-user", users: "x-fa fa-users", user_secret: "x-fa fa-user-secret", - video: "x-fa fa-video-camera" + video: "x-fa fa-video-camera", + video2x: "x-fa fa-video-camera fa-2x" } }) diff --git a/app/utils/locales.js b/app/utils/locales.js index fc05f3c5..f85083c5 100644 --- a/app/utils/locales.js +++ b/app/utils/locales.js @@ -1633,6 +1633,27 @@ Ext.define('Ngcp.csc.locales', { it: 'Video Call', fr: 'Video Call', sp: 'Video Call' + }, + start_call: { + en: 'Start call', + de: 'Start call', + it: 'Start call', + fr: 'Start call', + sp: 'Start call' + }, + incoming_call: { + en: 'Incoming call', + de: 'Incoming call', + it: 'Incoming call', + fr: 'Incoming call', + sp: 'Incoming call' + }, + incoming_call_from: { + en: 'Incoming {0} call from', + de: 'Incoming {0} call from', + it: 'Incoming {0} call from', + fr: 'Incoming {0} call from', + sp: 'Incoming {0} call from' } }, faxsend: { diff --git a/classic/sass/src/view/common/rtc/RtcPanel.scss b/classic/sass/src/view/common/rtc/RtcPanel.scss index cfa493f8..cd1fce26 100644 --- a/classic/sass/src/view/common/rtc/RtcPanel.scss +++ b/classic/sass/src/view/common/rtc/RtcPanel.scss @@ -59,3 +59,44 @@ $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; +} diff --git a/classic/sass/src/view/main/Main.scss b/classic/sass/src/view/main/Main.scss index fc20d37d..de30285f 100644 --- a/classic/sass/src/view/main/Main.scss +++ b/classic/sass/src/view/main/Main.scss @@ -255,3 +255,31 @@ border-radius: 20px; } } + +.csc-loading { + display: inline-block; + span { + animation-name: blink; + animation-duration: 1.4s; + animation-iteration-count: infinite; + animation-fill-mode: both; + &:nth-child(2) { + animation-delay: .2s; + } + &:nth-child(3) { + animation-delay: .4s; + } + } +} + +@keyframes blink { + 0% { + opacity: .2; + } + 20% { + opacity: 1; + } + 100% { + opacity: .2; + } +} diff --git a/classic/src/view/common/rtc/CallPanel.js b/classic/src/view/common/rtc/CallPanel.js index 657996fb..aa1f41ba 100644 --- a/classic/src/view/common/rtc/CallPanel.js +++ b/classic/src/view/common/rtc/CallPanel.js @@ -1,4 +1,3 @@ - Ext.define('NgcpCsc.view.common.rtc.CallPanel', { extend: 'Ext.form.Panel', alias: 'widget.call-panel', @@ -6,15 +5,59 @@ Ext.define('NgcpCsc.view.common.rtc.CallPanel', { bind: { hidden: '{!callPanel}' }, - items: [ - { + items: [{ bind: { hidden: '{!outgoingCallPending}' }, xtype: 'label', - text: 'Start call ...' + userCls: 'rtc-outgoing-label', + html: Ngcp.csc.locales.rtc.start_call[localStorage.getItem('languageSelected')] + Ngcp.csc.animations.loading_dots + }, + { + 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}') + } + }, { + 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' + } + }, { + xtype: 'button', + iconCls: Ngcp.csc.icons.phone_cancel2x, + userCls: 'rtc-decline-call', + pressedCls: 'rtc-decline-call-pressed', + width: 50, + height: 50, + listeners: { + click: 'declineCall' + } + }] } ] }); - - diff --git a/classic/src/view/common/rtc/RtcController.js b/classic/src/view/common/rtc/RtcController.js index e092fcc9..5671ed8d 100644 --- a/classic/src/view/common/rtc/RtcController.js +++ b/classic/src/view/common/rtc/RtcController.js @@ -146,6 +146,9 @@ Ext.define('NgcpCsc.view.common.rtc.RtcController', { vm.set('callPanelHidden', true); fieldToFocus = this.lookupReference('smsTextArea'); break; + case 'incomingCall': + me.showIncomingCallPendingState(); + break; } panel.show().expand(); if (fieldToFocus) { @@ -514,15 +517,8 @@ Ext.define('NgcpCsc.view.common.rtc.RtcController', { } }, - showOutgoingCallPendingState: function() { - this.getViewModel().set('callPanel', true); - this.getViewModel().set('outgoingCallPending', true); - this.getViewModel().set('phoneComposerHidden', true); - }, - - // parameter state true causes the class for the background color change to - // be added, and parameter state false causes the class to be removed setRtcpanelTitleColor: function (state) { + // parameter true to change color, and false to revert var rtcpanel = Ext.getCmp('rtcpanel'); rtcpanel.toggleCls('rtc-title-call-initiation', state); }, @@ -538,6 +534,48 @@ Ext.define('NgcpCsc.view.common.rtc.RtcController', { var sound = document.getElementById('ring'); sound.pause(); sound.currentTime = 0; + }, + + showOutgoingCallPendingState: function() { + var vm = this.getViewModel(); + vm.set('callPanel', true); + vm.set('outgoingCallPending', true); + vm.set('phoneComposerHidden', true); + }, + + showIncomingCallPendingState: function (caller, type) { + // @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 = caller || '+4312345'; + var type = 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); + this.setRtcpanelTitleColor(true); + }, + + hideIncomingCallPendingState: function () { + var vm = this.getViewModel(); + var rtcpanel = Ext.getCmp('rtcpanel'); + this.setRtcpanelTitleColor(false); + vm.set('callPanel', false); + vm.set('incomingCallPending', false); + vm.set('title', ''); + vm.set('incomingCaller', ''); + vm.set('incomingType', ''); + if (rtcpanel) { // Closes rtcpanel + rtcpanel.close(); + }; + }, + + declineCall: function () { + this.hideIncomingCallPendingState(); } }); diff --git a/classic/src/view/common/rtc/RtcModel.js b/classic/src/view/common/rtc/RtcModel.js index 2f8bd719..7494bfdd 100644 --- a/classic/src/view/common/rtc/RtcModel.js +++ b/classic/src/view/common/rtc/RtcModel.js @@ -6,7 +6,7 @@ Ext.define('NgcpCsc.view.rtc.RtcModel', { // left inline by purpose as it's not coming from API data: { uid: '', - title: 123456789, + title: '', defaultThumbnail: Ext.manifest.resources.path + '/images/icons/phoneicon.png', thumbnail: Ext.manifest.resources.path + '/images/icons/phoneicon.png', status: 'calling...', @@ -15,6 +15,7 @@ Ext.define('NgcpCsc.view.rtc.RtcModel', { faxComposerHidden: true, smsComposerHidden: true, phoneKeyboardHidden: true, + incomingCallHidden: true, callEnabled: false, connected: false, micEnabled: false, @@ -35,7 +36,10 @@ Ext.define('NgcpCsc.view.rtc.RtcModel', { rtcEngineClient: null, rtcEngineSession: null, callPanel: true, - outgoingCallPending: false + outgoingCallPending: false, + incomingCallPending: false, + incomingType: '', + incomingCaller: '' }, formulas: { disableSubmit: function(get) { diff --git a/classic/src/view/login/Login.js b/classic/src/view/login/Login.js index 58952aa9..8fcb7ab1 100644 --- a/classic/src/view/login/Login.js +++ b/classic/src/view/login/Login.js @@ -12,6 +12,11 @@ Ext.define('NgcpCsc.view.login.Login', { draggable: false, header: false, cls: 'auth-dialog', + listeners: { + beforeclose: function (e) { + return false; // prevents the login window to close on ESC key + } + }, items: { xtype: 'form', reference: 'login-form', diff --git a/classic/src/view/pages/conversations/ConversationsController.js b/classic/src/view/pages/conversations/ConversationsController.js index 4231de36..f2d73a79 100644 --- a/classic/src/view/pages/conversations/ConversationsController.js +++ b/classic/src/view/pages/conversations/ConversationsController.js @@ -174,7 +174,7 @@ Ext.define('NgcpCsc.view.pages.conversations.ConversationsController', { var storeReload = function(){ grid.getStore().load(); }; - + task = runner.start({ run: storeReload, interval: 60000