Commit 90c35eb2 authored by Ronan Abhamon's avatar Ronan Abhamon

feat(app): calls in progress

parent af60c28e
<?xml version="1.0" encoding="UTF-8"?>
<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 41 (35326) - http://www.bohemiancoding.com/sketch -->
<title>call_in_sign</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="call_in_sign">
<polygon fill="#DC4100" points="0 0 40 0 0 40"></polygon>
<path d="M11.243716,8.71501414 L11.1871835,8.71501414 C8.47215269,8.71501414 5.21235367,10.3895588 4.11804501,12.8152126 L4.51732144,15.956733 L8.01512006,15.956733 L8.2626641,12.830113 L14.1683578,12.830113 L14.41529,15.956733 L17.9130886,15.956733 L18.3123651,12.8149535 C17.2174446,10.3886518 13.9583798,8.71501414 11.243716,8.71501414 Z" fill="#FFFFFF" transform="translate(11.215205, 12.335874) rotate(-135.000000) translate(-11.215205, -12.335874) "></path>
</g>
</g>
</svg>
...@@ -40,15 +40,15 @@ ...@@ -40,15 +40,15 @@
</message> </message>
<message> <message>
<source>resumeCall</source> <source>resumeCall</source>
<translation type="unfinished"></translation> <translation>RESUME CALL</translation>
</message> </message>
<message> <message>
<source>transferCall</source> <source>transferCall</source>
<translation type="unfinished"></translation> <translation>TRANSFER CALL</translation>
</message> </message>
<message> <message>
<source>pauseCall</source> <source>pauseCall</source>
<translation type="unfinished"></translation> <translation>PAUSE CALL</translation>
</message> </message>
</context> </context>
<context> <context>
......
...@@ -32,15 +32,15 @@ ...@@ -32,15 +32,15 @@
</message> </message>
<message> <message>
<source>resumeCall</source> <source>resumeCall</source>
<translation type="unfinished"></translation> <translation>REPRENDRE APPEL</translation>
</message> </message>
<message> <message>
<source>transferCall</source> <source>transferCall</source>
<translation type="unfinished"></translation> <translation>TRANSFERER APPEL</translation>
</message> </message>
<message> <message>
<source>pauseCall</source> <source>pauseCall</source>
<translation type="unfinished"></translation> <translation>PAUSE</translation>
</message> </message>
</context> </context>
<context> <context>
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
<file>assets/images/call_quality_2.svg</file> <file>assets/images/call_quality_2.svg</file>
<file>assets/images/call_quality_3.svg</file> <file>assets/images/call_quality_3.svg</file>
<file>assets/images/call_sign_connected.svg</file> <file>assets/images/call_sign_connected.svg</file>
<file>assets/images/call_sign_ended.svg</file>
<file>assets/images/call_sign_incoming.svg</file> <file>assets/images/call_sign_incoming.svg</file>
<file>assets/images/call_sign_outgoing.svg</file> <file>assets/images/call_sign_outgoing.svg</file>
<file>assets/images/call_sign_paused.svg</file> <file>assets/images/call_sign_paused.svg</file>
......
...@@ -62,6 +62,14 @@ App::App (int &argc, char **argv) : QApplication(argc, argv) { ...@@ -62,6 +62,14 @@ App::App (int &argc, char **argv) : QApplication(argc, argv) {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
QQuickWindow *App::getCallsWindow () const {
QQuickWindow *window = m_engine.rootContext()->contextProperty("CallsWindow").value<QQuickWindow *>();
if (!window)
qFatal("Unable to get calls window.");
return window;
}
bool App::hasFocus () const { bool App::hasFocus () const {
QQmlApplicationEngine &engine = const_cast<QQmlApplicationEngine &>(m_engine); QQmlApplicationEngine &engine = const_cast<QQmlApplicationEngine &>(m_engine);
const QQuickWindow *root = qobject_cast<QQuickWindow *>(engine.rootObjects().at(0)); const QQuickWindow *root = qobject_cast<QQuickWindow *>(engine.rootObjects().at(0));
...@@ -182,7 +190,6 @@ void App::addContextProperties () { ...@@ -182,7 +190,6 @@ void App::addContextProperties () {
qInfo() << "Adding context properties..."; qInfo() << "Adding context properties...";
QQmlContext *context = m_engine.rootContext(); QQmlContext *context = m_engine.rootContext();
// TODO: Avoid context properties. Use qmlRegister...
QQmlComponent component(&m_engine, QUrl(QML_VIEW_CALL_WINDOW)); QQmlComponent component(&m_engine, QUrl(QML_VIEW_CALL_WINDOW));
if (component.isError()) { if (component.isError()) {
qWarning() << component.errors(); qWarning() << component.errors();
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include <QApplication> #include <QApplication>
#include <QQmlApplicationEngine> #include <QQmlApplicationEngine>
#include <QQmlFileSelector> #include <QQmlFileSelector>
#include <QQuickWindow>
#include <QSystemTrayIcon> #include <QSystemTrayIcon>
#include "../components/notifier/Notifier.hpp" #include "../components/notifier/Notifier.hpp"
...@@ -25,6 +26,8 @@ public: ...@@ -25,6 +26,8 @@ public:
return m_notifier; return m_notifier;
} }
QQuickWindow *getCallsWindow () const;
bool hasFocus () const; bool hasFocus () const;
Q_INVOKABLE QString locale () const { Q_INVOKABLE QString locale () const {
......
#include <QDebug> #include <QDebug>
#include <QTimer>
#include "../../app/App.hpp" #include "../../app/App.hpp"
#include "../core/CoreManager.hpp" #include "../core/CoreManager.hpp"
#include "CallsListModel.hpp" #include "CallsListModel.hpp"
/* Delay before removing call in ms. */
#define DELAY_BEFORE_REMOVE_CALL 3000
using namespace std; using namespace std;
// ============================================================================= // =============================================================================
...@@ -16,17 +20,16 @@ CallsListModel::CallsListModel (QObject *parent) : QAbstractListModel(parent) { ...@@ -16,17 +20,16 @@ CallsListModel::CallsListModel (QObject *parent) : QAbstractListModel(parent) {
this, [this](const shared_ptr<linphone::Call> &linphone_call, linphone::CallState state) { this, [this](const shared_ptr<linphone::Call> &linphone_call, linphone::CallState state) {
switch (state) { switch (state) {
case linphone::CallStateIncomingReceived: case linphone::CallStateIncomingReceived:
addCall(linphone_call);
break;
case linphone::CallStateOutgoingInit: case linphone::CallStateOutgoingInit:
addCall(linphone_call); addCall(linphone_call);
break; break;
case linphone::CallStateEnd: case linphone::CallStateEnd:
case linphone::CallStateError: case linphone::CallStateError:
removeCall(linphone_call); removeCall(linphone_call);
break; break;
default:
default:
break; break;
} }
} }
...@@ -80,11 +83,13 @@ bool CallsListModel::removeRows (int row, int count, const QModelIndex &parent) ...@@ -80,11 +83,13 @@ bool CallsListModel::removeRows (int row, int count, const QModelIndex &parent)
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void CallsListModel::addCall (const shared_ptr<linphone::Call> &linphone_call) { void CallsListModel::addCall (const shared_ptr<linphone::Call> &linphone_call) {
App::getInstance()->getCallsWindow()->show();
CallModel *call = new CallModel(linphone_call); CallModel *call = new CallModel(linphone_call);
App::getInstance()->getEngine()->setObjectOwnership(call, QQmlEngine::CppOwnership); App::getInstance()->getEngine()->setObjectOwnership(call, QQmlEngine::CppOwnership);
linphone_call->setData("call-model", *call); linphone_call->setData("call-model", *call);
int row = rowCount(); int row = m_list.count();
beginInsertRows(QModelIndex(), row, row); beginInsertRows(QModelIndex(), row, row);
m_list << call; m_list << call;
...@@ -92,12 +97,20 @@ void CallsListModel::addCall (const shared_ptr<linphone::Call> &linphone_call) { ...@@ -92,12 +97,20 @@ void CallsListModel::addCall (const shared_ptr<linphone::Call> &linphone_call) {
} }
void CallsListModel::removeCall (const shared_ptr<linphone::Call> &linphone_call) { void CallsListModel::removeCall (const shared_ptr<linphone::Call> &linphone_call) {
CallModel &call = linphone_call->getData<CallModel>("call-model"); CallModel *call = &linphone_call->getData<CallModel>("call-model");
linphone_call->unsetData("call-model"); linphone_call->unsetData("call-model");
qInfo() << "Removing call:" << &call; // TODO: It will be (maybe) necessary to use a single scheduled function in the future.
QTimer::singleShot(
DELAY_BEFORE_REMOVE_CALL, this, [this, call]() {
qInfo() << "Removing call:" << call;
int index = m_list.indexOf(&call); int index = m_list.indexOf(call);
if (index == -1 || !removeRow(index)) if (index == -1 || !removeRow(index))
qWarning() << "Unable to remove call:" << &call; qWarning() << "Unable to remove call:" << call;
if (m_list.empty())
App::getInstance()->getCallsWindow()->close();
}
);
} }
...@@ -520,7 +520,7 @@ void ChatModel::removeEntry (ChatEntryData &pair) { ...@@ -520,7 +520,7 @@ void ChatModel::removeEntry (ChatEntryData &pair) {
} }
void ChatModel::insertMessageAtEnd (const shared_ptr<linphone::ChatMessage> &message) { void ChatModel::insertMessageAtEnd (const shared_ptr<linphone::ChatMessage> &message) {
int row = rowCount(); int row = m_entries.count();
beginInsertRows(QModelIndex(), row, row); beginInsertRows(QModelIndex(), row, row);
......
...@@ -92,7 +92,7 @@ ContactModel *ContactsListModel::addContact (VcardModel *vcard) { ...@@ -92,7 +92,7 @@ ContactModel *ContactsListModel::addContact (VcardModel *vcard) {
return nullptr; return nullptr;
} }
int row = rowCount(); int row = m_list.count();
beginInsertRows(QModelIndex(), row, row); beginInsertRows(QModelIndex(), row, row);
addContact(contact); addContact(contact);
......
...@@ -21,8 +21,7 @@ ListView { ...@@ -21,8 +21,7 @@ ListView {
function _getSignIcon (call) { function _getSignIcon (call) {
if (call) { if (call) {
var string = _mapStatusToParams[call.status].string return 'call_sign_' + _mapStatusToParams[call.status].string
return string ? 'call_sign_' + string : ''
} }
return '' return ''
...@@ -60,7 +59,9 @@ ListView { ...@@ -60,7 +59,9 @@ ListView {
string: 'connected' string: 'connected'
} }
_mapStatusToParams[CallModel.CallStatusEnded] = {} _mapStatusToParams[CallModel.CallStatusEnded] = {
string: 'ended'
}
_mapStatusToParams[CallModel.CallStatusIncoming] = { _mapStatusToParams[CallModel.CallStatusIncoming] = {
actions: [{ actions: [{
...@@ -121,7 +122,9 @@ ListView { ...@@ -121,7 +122,9 @@ ListView {
ActionButton { ActionButton {
id: button id: button
icon: 'burger_menu' icon: calls.currentIndex === callId && call.status !== CallModel.CallStatusEnded
? 'burger_menu_light'
: 'burger_menu'
iconSize: CallsStyle.entry.iconMenuSize iconSize: CallsStyle.entry.iconMenuSize
onClicked: menu.showMenu() onClicked: menu.showMenu()
...@@ -162,11 +165,26 @@ ListView { ...@@ -162,11 +165,26 @@ ListView {
delegate: CallControls { delegate: CallControls {
id: _callControls id: _callControls
function useColorStatus () {
return calls.currentIndex === index && $call.status !== CallModel.CallStatusEnded
}
color: useColorStatus()
? CallsStyle.entry.color.selected
: CallsStyle.entry.color.normal
sipAddressColor: useColorStatus()
? CallsStyle.entry.sipAddressColor.selected
: CallsStyle.entry.sipAddressColor.normal
usernameColor: useColorStatus()
? CallsStyle.entry.usernameColor.selected
: CallsStyle.entry.usernameColor.normal
signIcon: _getSignIcon($call) signIcon: _getSignIcon($call)
sipAddress: $call.sipAddress sipAddress: $call.sipAddress
width: parent.width width: parent.width
Loader { Loader {
property int callId: index
property var call: $call property var call: $call
property var callControls: _callControls property var callControls: _callControls
property var params: _getParams($call) property var params: _getParams($call)
...@@ -174,5 +192,22 @@ ListView { ...@@ -174,5 +192,22 @@ ListView {
anchors.centerIn: parent anchors.centerIn: parent
sourceComponent: params.component sourceComponent: params.component
} }
SequentialAnimation on color {
loops: CallsStyle.entry.endCallAnimation.loops
running: $call.status === CallModel.CallStatusEnded
ColorAnimation {
duration: CallsStyle.entry.endCallAnimation.duration
from: CallsStyle.entry.color.normal
to: CallsStyle.entry.endCallAnimation.blinkColor
}
ColorAnimation {
duration: CallsStyle.entry.endCallAnimation.duration
from: CallsStyle.entry.endCallAnimation.blinkColor
to: CallsStyle.entry.color.normal
}
}
} }
} }
...@@ -11,5 +11,26 @@ QtObject { ...@@ -11,5 +11,26 @@ QtObject {
property int iconMenuSize: 17 property int iconMenuSize: 17
property int height: 30 property int height: 30
property int width: 200 property int width: 200
property QtObject color: QtObject {
property color normal: Colors.e
property color selected: Colors.j
}
property QtObject endCallAnimation: QtObject {
property color blinkColor: Colors.i
property int duration: 300
property int loops: 3
}
property QtObject sipAddressColor: QtObject {
property color normal: Colors.w
property color selected: Colors.k
}
property QtObject usernameColor: QtObject {
property color normal: Colors.j
property color selected: Colors.k
}
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment