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 @@
</message>
<message>
<source>resumeCall</source>
<translation type="unfinished"></translation>
<translation>RESUME CALL</translation>
</message>
<message>
<source>transferCall</source>
<translation type="unfinished"></translation>
<translation>TRANSFER CALL</translation>
</message>
<message>
<source>pauseCall</source>
<translation type="unfinished"></translation>
<translation>PAUSE CALL</translation>
</message>
</context>
<context>
......
......@@ -32,15 +32,15 @@
</message>
<message>
<source>resumeCall</source>
<translation type="unfinished"></translation>
<translation>REPRENDRE APPEL</translation>
</message>
<message>
<source>transferCall</source>
<translation type="unfinished"></translation>
<translation>TRANSFERER APPEL</translation>
</message>
<message>
<source>pauseCall</source>
<translation type="unfinished"></translation>
<translation>PAUSE</translation>
</message>
</context>
<context>
......
......@@ -26,6 +26,7 @@
<file>assets/images/call_quality_2.svg</file>
<file>assets/images/call_quality_3.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_outgoing.svg</file>
<file>assets/images/call_sign_paused.svg</file>
......
......@@ -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 {
QQmlApplicationEngine &engine = const_cast<QQmlApplicationEngine &>(m_engine);
const QQuickWindow *root = qobject_cast<QQuickWindow *>(engine.rootObjects().at(0));
......@@ -182,7 +190,6 @@ void App::addContextProperties () {
qInfo() << "Adding context properties...";
QQmlContext *context = m_engine.rootContext();
// TODO: Avoid context properties. Use qmlRegister...
QQmlComponent component(&m_engine, QUrl(QML_VIEW_CALL_WINDOW));
if (component.isError()) {
qWarning() << component.errors();
......
......@@ -4,6 +4,7 @@
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQmlFileSelector>
#include <QQuickWindow>
#include <QSystemTrayIcon>
#include "../components/notifier/Notifier.hpp"
......@@ -25,6 +26,8 @@ public:
return m_notifier;
}
QQuickWindow *getCallsWindow () const;
bool hasFocus () const;
Q_INVOKABLE QString locale () const {
......
#include <QDebug>
#include <QTimer>
#include "../../app/App.hpp"
#include "../core/CoreManager.hpp"
#include "CallsListModel.hpp"
/* Delay before removing call in ms. */
#define DELAY_BEFORE_REMOVE_CALL 3000
using namespace std;
// =============================================================================
......@@ -16,17 +20,16 @@ CallsListModel::CallsListModel (QObject *parent) : QAbstractListModel(parent) {
this, [this](const shared_ptr<linphone::Call> &linphone_call, linphone::CallState state) {
switch (state) {
case linphone::CallStateIncomingReceived:
addCall(linphone_call);
break;
case linphone::CallStateOutgoingInit:
addCall(linphone_call);
break;
case linphone::CallStateEnd:
case linphone::CallStateError:
removeCall(linphone_call);
break;
default:
default:
break;
}
}
......@@ -80,11 +83,13 @@ bool CallsListModel::removeRows (int row, int count, const QModelIndex &parent)
// -----------------------------------------------------------------------------
void CallsListModel::addCall (const shared_ptr<linphone::Call> &linphone_call) {
App::getInstance()->getCallsWindow()->show();
CallModel *call = new CallModel(linphone_call);
App::getInstance()->getEngine()->setObjectOwnership(call, QQmlEngine::CppOwnership);
linphone_call->setData("call-model", *call);
int row = rowCount();
int row = m_list.count();
beginInsertRows(QModelIndex(), row, row);
m_list << 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) {
CallModel &call = linphone_call->getData<CallModel>("call-model");
CallModel *call = &linphone_call->getData<CallModel>("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))
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) {
}
void ChatModel::insertMessageAtEnd (const shared_ptr<linphone::ChatMessage> &message) {
int row = rowCount();
int row = m_entries.count();
beginInsertRows(QModelIndex(), row, row);
......
......@@ -92,7 +92,7 @@ ContactModel *ContactsListModel::addContact (VcardModel *vcard) {
return nullptr;
}
int row = rowCount();
int row = m_list.count();
beginInsertRows(QModelIndex(), row, row);
addContact(contact);
......
......@@ -21,8 +21,7 @@ ListView {
function _getSignIcon (call) {
if (call) {
var string = _mapStatusToParams[call.status].string
return string ? 'call_sign_' + string : ''
return 'call_sign_' + _mapStatusToParams[call.status].string
}
return ''
......@@ -60,7 +59,9 @@ ListView {
string: 'connected'
}
_mapStatusToParams[CallModel.CallStatusEnded] = {}
_mapStatusToParams[CallModel.CallStatusEnded] = {
string: 'ended'
}
_mapStatusToParams[CallModel.CallStatusIncoming] = {
actions: [{
......@@ -121,7 +122,9 @@ ListView {
ActionButton {
id: button
icon: 'burger_menu'
icon: calls.currentIndex === callId && call.status !== CallModel.CallStatusEnded
? 'burger_menu_light'
: 'burger_menu'
iconSize: CallsStyle.entry.iconMenuSize
onClicked: menu.showMenu()
......@@ -162,11 +165,26 @@ ListView {
delegate: 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)
sipAddress: $call.sipAddress
width: parent.width
Loader {
property int callId: index
property var call: $call
property var callControls: _callControls
property var params: _getParams($call)
......@@ -174,5 +192,22 @@ ListView {
anchors.centerIn: parent
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 {
property int iconMenuSize: 17
property int height: 30
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