From d3a43fa47a1bd6ef24dcb4476cd29d1de264b510 Mon Sep 17 00:00:00 2001 From: Hans-Peter Herzog Date: Wed, 30 Aug 2017 10:30:36 +0200 Subject: [PATCH] TT#20504 Call: As a Customer, I want to initiate an audio/video call - Call: Implement ringing state - Call: Implement pending state - Call: Implement call cancellation Change-Id: Ia38f5a7867c1eba6677b71893549a7b21fdd9ef2 --- .../sass/src/view/common/rtc/RtcPanel.scss | 64 ++++++++++++++ classic/src/view/common/rtc/CallPanel.js | 49 +++++++++-- classic/src/view/common/rtc/RtcController.js | 85 +++++++++++++------ classic/src/view/common/rtc/RtcModel.js | 31 ++++++- classic/src/view/common/rtc/composer/Phone.js | 22 +++-- 5 files changed, 209 insertions(+), 42 deletions(-) diff --git a/classic/sass/src/view/common/rtc/RtcPanel.scss b/classic/sass/src/view/common/rtc/RtcPanel.scss index cd1fce26..9cd1ac50 100644 --- a/classic/sass/src/view/common/rtc/RtcPanel.scss +++ b/classic/sass/src/view/common/rtc/RtcPanel.scss @@ -100,3 +100,67 @@ $border-radius : 50%; .rtc-button-margin { margin: 0 50px 0 0; } + +.call-button { + border-radius: 50%; + background-color: #16b603; + color: white; + border-width: 0; +} + +.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 { + background-color: red; +} + +.call-button-accept { + background-color: forestgreen; +} + +.call-icon-cancel { + position: absolute; + transform: rotate(135deg); + font-size: 22px; + top: 2px; + left: 4px; +} + +.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-focus, +.call-button-accept-over { + background-color: darkgreen; +} + +#call-local-preview { + width: 100%; +} + +.x-panel-body-default { + label.call-number-label { + font-size: 16px; + font-weight: bold; + } +} diff --git a/classic/src/view/common/rtc/CallPanel.js b/classic/src/view/common/rtc/CallPanel.js index aa1f41ba..66333d1e 100644 --- a/classic/src/view/common/rtc/CallPanel.js +++ b/classic/src/view/common/rtc/CallPanel.js @@ -1,18 +1,51 @@ + Ext.define('NgcpCsc.view.common.rtc.CallPanel', { extend: 'Ext.form.Panel', alias: 'widget.call-panel', - layout: 'center', + padding: '60 0 0 0', bind: { - hidden: '{!callPanel}' + hidden: '{!callEnabled}' }, items: [{ - bind: { - hidden: '{!outgoingCallPending}' - }, - xtype: 'label', - userCls: 'rtc-outgoing-label', - html: Ngcp.csc.locales.rtc.start_call[localStorage.getItem('languageSelected')] + Ngcp.csc.animations.loading_dots + layout : { + type : 'vbox', + align : 'center', + pack: 'center', + + }, + bind: { + hidden: '{!outgoingCall}' }, + items: [ + { + bind: { + text: '{callActionLabel}' + }, + xtype: 'label', + margin: '0 0 20 0' + }, + { + bind: { + text: '{numberToCall}' + }, + xtype: 'label', + margin: '0 0 20 0', + userCls: 'call-number-label', + }, + { + 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' + } + } + ]}, { bind: { hidden: '{!incomingCallPending}' diff --git a/classic/src/view/common/rtc/RtcController.js b/classic/src/view/common/rtc/RtcController.js index 5671ed8d..d76d3a28 100644 --- a/classic/src/view/common/rtc/RtcController.js +++ b/classic/src/view/common/rtc/RtcController.js @@ -27,12 +27,26 @@ 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(); + $vm.set('rtcEngineLocalMediaStream', null); + } this.createMedia(mediaType).then(function (localMediaStream) { + // Todo: attache stream to video element + // if(mediaType === 'video') { + // cdk.MediaElementHelper.attachStreamToDomNode( + // document.getElementById('call-local-preview'), + // localMediaStream + // ); + // } var call = network.call(callee, { localMediaStream: localMediaStream }); call.onPending(function () { $ct.outgoingPending(); }) .onAccepted(function () { $ct.outgoingAccepted(); }) @@ -96,7 +110,7 @@ Ext.define('NgcpCsc.view.common.rtc.RtcController', { vm.set('title', Ext.String.format(Ngcp.csc.locales.rtc.calling[localStorage.getItem('languageSelected')], number)); vm.set('thumbnail', record.get('thumbnail') || this.getViewModel().get('defaultThumbnail')); vm.set('status', Ext.String.format(Ngcp.csc.locales.rtc.calling[localStorage.getItem('languageSelected')] + ' ...', number)); - vm.set('callEnabled', false); + vm.set('callPanelEnabled', false); vm.set('micEnabled', false); vm.set('phoneComposerHidden', true); vm.set('faxComposerHidden', true); @@ -146,9 +160,6 @@ 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) { @@ -221,7 +232,7 @@ Ext.define('NgcpCsc.view.common.rtc.RtcController', { setTimeout(function() { var seconds = minutes = hours = 0; me.stopRingSound(); - vm.set('callEnabled', true); + vm.set('callPanelEnabled', true); vm.set('micEnabled', true); me.startMedia(audioOn, videoOn); @@ -264,7 +275,7 @@ Ext.define('NgcpCsc.view.common.rtc.RtcController', { }, toggleCall: function(btn) { - if (btn.pressed) { // this can be also checked against vm.get('callEnabled') + if (btn.pressed) { // this can be also checked against vm.get('callPanelEnabled') this.emulateCall(true, false); } else { this.endCall(); @@ -439,22 +450,22 @@ Ext.define('NgcpCsc.view.common.rtc.RtcController', { var rtcNetwork = rtcClient.getNetworkByTag('sip'); $vm.set('rtcEngineNetwork', rtcNetwork); rtcNetwork.onConnect(function() { - $vm.set('callEnabled', true); + $vm.set('callPanelEnabled', true); }).onIncomingCall(function(call) { - call.onPending(function(){ $ct.incomingCallPending(); }) - .onRemoteMedia(function(stream){ $ct.incomingRemoteMedia(stream); }) + $ct.incomingCallPending(); + call.onRemoteMedia(function(stream){ $ct.incomingRemoteMedia(stream); }) .onRemoteMediaEnded(function(){ $ct.incomingRemoteMediaEnded(); }) .onEnded(function(){ $ct.incomingRemoteMediaEnded() }); }).onDisconnect(function(){ - $vm.set('callEnabled', false); + $vm.set('callPanelEnabled', false); $vm.set('callDisabledReason', rtcNetwork.disconnectReason); }); }).onDisconnect(function(){ - $vm.set('callEnabled', false); + $vm.set('callPanelEnabled', false); $vm.set('callDisabledReason', rtcClient.disconnectReason); }); }).catch(function(err){ - $vm.set('callEnabled', false); + $vm.set('callPanelEnabled', false); $vm.set('callDisabledReason', err.message); console.error(err); }); @@ -471,10 +482,12 @@ Ext.define('NgcpCsc.view.common.rtc.RtcController', { outgoingRingingStart: function() { console.log('outgoingCallRingingStart'); + this.showOutgoingCallRingingState(); }, outgoingRingingStop: function() { console.log('outgoingCallRingingStop'); + this.stopRingSound(); }, outgoingRemoteMedia: function(stream) { @@ -491,6 +504,8 @@ Ext.define('NgcpCsc.view.common.rtc.RtcController', { }, incomingCallPending: function() { + this.getView().show().expand(); + this.showIncomingCallPendingState(); console.log('incomingCallPending'); }, @@ -510,13 +525,38 @@ Ext.define('NgcpCsc.view.common.rtc.RtcController', { callEnded: function() { var $ct = this; var $vm = $ct.getViewModel(); - var localMediaStream = $vm.get('rtcEngineLocalMediaStream'); - if(localMediaStream !== null) { - localMediaStream.stop(); - $vm.set('rtcEngineLocalMediaStream', null); + }, + + cancelOutgoingCall: function() { + var call = this.getViewModel().get('rtcEngineCall'); + var mediaStream = this.getViewModel().get('rtcEngineLocalMediaStream'); + this.getViewModel().set('phoneComposerHidden', false); + this.getViewModel().set('callPending', false); + this.getViewModel().set('callRinging', false); + this.stopRingSound(); + if(call !== null) { + call.end(); } + if(mediaStream !== null) { + mediaStream.stop(); + } + }, + + showOutgoingCallPendingState: function() { + this.getViewModel().set('callPending', true); + this.getViewModel().set('callActionLabel', 'Try to call'); + this.getViewModel().set('phoneComposerHidden', true); }, + showOutgoingCallRingingState: function() { + this.getViewModel().set('callRinging', true); + this.getViewModel().set('callPending', false); + this.getViewModel().set('callActionLabel', 'Ringing'); + 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 setRtcpanelTitleColor: function (state) { // parameter true to change color, and false to revert var rtcpanel = Ext.getCmp('rtcpanel'); @@ -536,20 +576,13 @@ Ext.define('NgcpCsc.view.common.rtc.RtcController', { 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) { + 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 = caller || '+4312345'; - var type = type || 'audio'; + var caller = '+4312345'; + var type = 'audio'; vm.set('callPanel', true); vm.set('incomingCallPending', true); vm.set('phoneComposerHidden', true); diff --git a/classic/src/view/common/rtc/RtcModel.js b/classic/src/view/common/rtc/RtcModel.js index 7494bfdd..cfc2d58e 100644 --- a/classic/src/view/common/rtc/RtcModel.js +++ b/classic/src/view/common/rtc/RtcModel.js @@ -16,7 +16,7 @@ Ext.define('NgcpCsc.view.rtc.RtcModel', { smsComposerHidden: true, phoneKeyboardHidden: true, incomingCallHidden: true, - callEnabled: false, + callPanelEnabled: false, connected: false, micEnabled: false, videoEnabled: false, @@ -36,6 +36,9 @@ Ext.define('NgcpCsc.view.rtc.RtcModel', { rtcEngineClient: null, rtcEngineSession: null, callPanel: true, + callActionLabel: '', + callPending: false, + callRinging: false, outgoingCallPending: false, incomingCallPending: false, incomingType: '', @@ -54,7 +57,31 @@ Ext.define('NgcpCsc.view.rtc.RtcModel', { return get('numberToCall').length < 1; }, setuserCls:function(get){ - return get('callEnabled') ? '' : 'fa-rotate-180'; + return get('callPanelEnabled') ? '' : 'fa-rotate-180'; + }, + callEnabled: { + bind: { + callPending: '{callPending}', + callRinging: '{callRinging}', + incomingCallPending: '{incomingCallPending}' + }, + get: function (data) { + return data.callPending || data.callRinging || data.incomingCallPending; + } + }, + outgoingCall: { + bind: { + callPending: '{callPending}', + callRinging: '{callRinging}' + }, + get: function (data) { + return data.callPending || data.callRinging; + } + }, + callLocalPreview: { + get: function (data) { + return data.rtcEngineLocalMediaStream && data.rtcEngineLocalMediaStream.hasVideo(); + } } } }); diff --git a/classic/src/view/common/rtc/composer/Phone.js b/classic/src/view/common/rtc/composer/Phone.js index bf2710e0..67618792 100644 --- a/classic/src/view/common/rtc/composer/Phone.js +++ b/classic/src/view/common/rtc/composer/Phone.js @@ -35,19 +35,29 @@ Ext.define('NgcpCsc.view.common.rtc.composer.Phone', { xtype: 'container', items: [{ xtype: 'button', - text: Ngcp.csc.locales.rtc.sendAudio[localStorage.getItem('languageSelected')], - iconCls: Ngcp.csc.icons.microphone, + text: '', margin: '0 10 0 0', listeners: { click: 'sendAudio' - } + }, + userCls: 'call-button call-button-accept', + overCls: 'call-button-accept-over', + focusCls: 'call-button-accept-focus', + width: 40, + height: 40, + html: '' }, { xtype: 'button', - text: Ngcp.csc.locales.rtc.sendVideo[localStorage.getItem('languageSelected')], - iconCls: Ngcp.csc.icons.video, + text: '', listeners: { click: 'sendVideo' - } + }, + userCls: 'call-button call-button-accept', + overCls: 'call-button-accept-over', + focusCls: 'call-button-accept-focus', + width: 40, + height: 40, + html: '' }] }] }, {