Commit 2b5cb6bc authored by Ronan Abhamon's avatar Ronan Abhamon

feat(src/components/notifier/Notifier): supports messages & calls notifications

parent 40ee4028
<?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="#FF5E00" 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>
\ No newline at end of file
<?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="#FF5E00" 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>
\ No newline at end of file
......@@ -78,6 +78,7 @@
<file>assets/images/edit_normal.svg</file>
<file>assets/images/edit_pressed.svg</file>
<file>assets/images/ended_call.svg</file>
<file>assets/images/file_sign.svg</file>
<file>assets/images/filter.svg</file>
<file>assets/images/fullscreen_hovered.svg</file>
<file>assets/images/fullscreen_normal.svg</file>
......@@ -101,6 +102,7 @@
<file>assets/images/led_red.svg</file>
<file>assets/images/led_white.svg</file>
<file>assets/images/linphone.png</file>
<file>assets/images/message_sign.svg</file>
<file>assets/images/micro_off_hovered.svg</file>
<file>assets/images/micro_off_normal.svg</file>
<file>assets/images/micro_off_pressed.svg</file>
......@@ -228,9 +230,10 @@
<file>ui/modules/Linphone/Contact/ContactDescription.qml</file>
<file>ui/modules/Linphone/Contact/Contact.qml</file>
<file>ui/modules/Linphone/Contact/MessagesCounter.qml</file>
<file>ui/modules/Linphone/Notifications/CallNotification.qml</file>
<file>ui/modules/Linphone/Notifications/Notification.qml</file>
<file>ui/modules/Linphone/Notifications/ReceivedMessageNotification.qml</file>
<file>ui/modules/Linphone/Notifications/NotificationReceivedCall.qml</file>
<file>ui/modules/Linphone/Notifications/NotificationReceivedFileMessage.qml</file>
<file>ui/modules/Linphone/Notifications/NotificationReceivedMessage.qml</file>
<file>ui/modules/Linphone/Presence/PresenceLevel.qml</file>
<file>ui/modules/Linphone/Presence/PresenceString.qml</file>
<file>ui/modules/Linphone/qmldir</file>
......@@ -243,7 +246,10 @@
<file>ui/modules/Linphone/Styles/Contact/ContactDescriptionStyle.qml</file>
<file>ui/modules/Linphone/Styles/Contact/ContactStyle.qml</file>
<file>ui/modules/Linphone/Styles/Contact/MessagesCounterStyle.qml</file>
<file>ui/modules/Linphone/Styles/NotificationStyle.qml</file>
<file>ui/modules/Linphone/Styles/Notifications/NotificationReceivedCallStyle.qml</file>
<file>ui/modules/Linphone/Styles/Notifications/NotificationReceivedFileMessageStyle.qml</file>
<file>ui/modules/Linphone/Styles/Notifications/NotificationReceivedMessageStyle.qml</file>
<file>ui/modules/Linphone/Styles/Notifications/NotificationStyle.qml</file>
<file>ui/modules/Linphone/Styles/Presence/PresenceStringStyle.qml</file>
<file>ui/modules/Linphone/Styles/qmldir</file>
<file>ui/modules/Linphone/Styles/SmartSearchBarStyle.qml</file>
......
......@@ -92,10 +92,13 @@ QQuickWindow *App::getCallsWindow () const {
return window;
}
bool App::hasFocus () const {
QQuickWindow *App::getMainWindow () const {
QQmlApplicationEngine &engine = const_cast<QQmlApplicationEngine &>(m_engine);
const QQuickWindow *root = qobject_cast<QQuickWindow *>(engine.rootObjects().at(0));
return !!root->activeFocusItem();
return qobject_cast<QQuickWindow *>(engine.rootObjects().at(0));
}
bool App::hasFocus () const {
return getMainWindow()->isActive() || getCallsWindow()->isActive();
}
// -----------------------------------------------------------------------------
......@@ -109,6 +112,9 @@ void App::initContentApp () {
registerTypes();
addContextProperties();
// Enable notifications.
m_notifier = new Notifier();
CoreManager::getInstance()->enableHandlers();
// Load main view.
......@@ -167,7 +173,7 @@ void App::registerTypes () {
qmlRegisterSingletonType<CallsListModel>(
"Linphone", 1, 0, "CallsListModel",
[](QQmlEngine *, QJSEngine *) -> QObject *{
return new CallsListModel();
return CoreManager::getInstance()->getCallsListModel();
}
);
......@@ -219,13 +225,10 @@ void App::addContextProperties () {
}
context->setContextProperty("CallsWindow", component.create());
m_notifier = new Notifier();
context->setContextProperty("Notifier", m_notifier);
}
void App::setTrayIcon () {
QQuickWindow *root = qobject_cast<QQuickWindow *>(m_engine.rootObjects().at(0));
QQuickWindow *root = getMainWindow();
QMenu *menu = new QMenu();
m_system_tray_icon = new QSystemTrayIcon(root);
......
......@@ -49,6 +49,7 @@ public:
}
QQuickWindow *getCallsWindow () const;
QQuickWindow *getMainWindow () const;
bool hasFocus () const;
......
......@@ -226,18 +226,15 @@ float CallModel::getQuality () const {
}
bool CallModel::getMicroMuted () const {
return m_micro_muted;
return !CoreManager::getInstance()->getCore()->micEnabled();
}
void CallModel::setMicroMuted (bool status) {
if (m_micro_muted != status) {
m_micro_muted = status;
shared_ptr<linphone::Core> core = CoreManager::getInstance()->getCore();
if (m_micro_muted == core->micEnabled())
core->enableMic(!m_micro_muted);
emit microMutedChanged(m_micro_muted);
if (status != core->micEnabled()) {
core->enableMic(!status);
emit microMutedChanged(status);
}
}
......
......@@ -109,7 +109,6 @@ private:
bool getRecording () const;
bool m_micro_muted = false;
bool m_paused_by_remote = false;
bool m_paused_by_user = false;
bool m_recording = false;
......
......@@ -81,6 +81,16 @@ QVariant CallsListModel::data (const QModelIndex &index, int role) const {
return QVariant();
}
CallModel *CallsListModel::getCall (const shared_ptr<linphone::Call> &linphone_call) const {
auto it = find_if(
m_list.begin(), m_list.end(), [linphone_call](CallModel *call) {
return linphone_call == call->getLinphoneCall();
}
);
return it != m_list.end() ? *it : nullptr;
}
// -----------------------------------------------------------------------------
void CallsListModel::launchAudioCall (const QString &sip_uri) const {
......
......@@ -43,6 +43,8 @@ public:
QHash<int, QByteArray> roleNames () const override;
QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override;
CallModel *getCall (const std::shared_ptr<linphone::Call> &linphone_call) const;
Q_INVOKABLE void launchAudioCall (const QString &sip_uri) const;
Q_INVOKABLE void launchVideoCall (const QString &sip_uri) const;
......
#include <QOpenGLFunctions>
/*
* MSFunctions.cpp
* Copyright (C) 2017 Belledonne Communications, Grenoble, France
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Created on: February 9, 2017
* Author: Ronan Abhamon
*/
#include "MSFunctions.hpp"
// Do not include this header before `QOpenGLFunctions`!!!
#include <mediastreamer2/msogl.h>
#include "MSFunctions.hpp"
// =============================================================================
MSFunctions *MSFunctions::m_instance = nullptr;
......
/*
* MSFunctions.hpp
* Copyright (C) 2017 Belledonne Communications, Grenoble, France
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Created on: February 9, 2017
* Author: Ronan Abhamon
*/
#ifndef MS_FUNCTIONS_H_
#define MS_FUNCTIONS_H_
......
......@@ -30,6 +30,7 @@
#include <QTimer>
#include <QUuid>
#include "../../app/App.hpp"
#include "../../app/Paths.hpp"
#include "../../app/ThumbnailProvider.hpp"
#include "../../utils.hpp"
......@@ -150,9 +151,11 @@ private:
if (it == m_chat_model->m_entries.end())
return;
// File message downloaded.
if (state == linphone::ChatMessageStateFileTransferDone && !message->isOutgoing()) {
createThumbnail(message);
fillThumbnailProperty((*it).first, message);
App::getInstance()->getNotifier()->notifyReceivedFileMessage(message);
}
(*it).first["status"] = state;
......
......@@ -46,16 +46,19 @@ void CoreHandlers::onCallStateChanged (
const string &
) {
emit callStateChanged(call, state);
if (call->getState() == linphone::CallStateIncomingReceived)
App::getInstance()->getNotifier()->notifyReceivedCall(call);
}
void CoreHandlers::onMessageReceived (
const shared_ptr<linphone::Core> &,
const shared_ptr<linphone::ChatRoom> &room,
const shared_ptr<linphone::ChatRoom> &,
const shared_ptr<linphone::ChatMessage> &message
) {
emit messageReceived(message);
const App *app = App::getInstance();
if (!app->hasFocus())
app->getNotifier()->notifyReceivedMessage(10000, room, message);
app->getNotifier()->notifyReceivedMessage(message);
}
......@@ -49,6 +49,7 @@ void CoreManager::init () {
if (!m_instance) {
m_instance = new CoreManager();
m_instance->m_calls_list_model = new CallsListModel(m_instance);
m_instance->m_contacts_list_model = new ContactsListModel(m_instance);
m_instance->m_sip_addresses_model = new SipAddressesModel(m_instance);
......
......@@ -23,6 +23,7 @@
#ifndef CORE_MANAGER_H_
#define CORE_MANAGER_H_
#include "../calls/CallsListModel.hpp"
#include "../contacts/ContactsListModel.hpp"
#include "../sip-addresses/SipAddressesModel.hpp"
#include "CoreHandlers.hpp"
......@@ -51,6 +52,10 @@ public:
// Singleton models.
// ---------------------------------------------------------------------------
CallsListModel *getCallsListModel () const {
return m_calls_list_model;
}
ContactsListModel *getContactsListModel () const {
return m_contacts_list_model;
}
......@@ -83,6 +88,7 @@ private:
std::shared_ptr<linphone::Core> m_core;
std::shared_ptr<CoreHandlers> m_handlers;
CallsListModel *m_calls_list_model;
ContactsListModel *m_contacts_list_model;
SipAddressesModel *m_sip_addresses_model;
......
......@@ -20,23 +20,31 @@
* Author: Ronan Abhamon
*/
#include "../../app/App.hpp"
#include "Notifier.hpp"
#include <QQmlComponent>
#include <QQuickWindow>
#include <QtDebug>
#include <QTimer>
#include "../../app/App.hpp"
#include "../../utils.hpp"
#include "../core/CoreManager.hpp"
#include "Notifier.hpp"
// Notifications QML properties/methods.
#define NOTIFICATION_SHOW_METHOD_NAME "show"
#define NOTIFICATION_HEIGHT_PROPERTY "notificationHeight"
#define NOTIFICATION_OFFSET_PROPERTY_NAME "notificationOffset"
#define NOTIFICATION_PROPERTY_DATA "notificationData"
#define NOTIFICATION_PROPERTY_HEIGHT "notificationHeight"
#define NOTIFICATION_PROPERTY_OFFSET "notificationOffset"
#define QML_CALL_NOTIFICATION_PATH "qrc:/ui/modules/Linphone/Notifications/CallNotification.qml"
#define QML_MESSAGE_RECEIVED_NOTIFICATION_PATH "qrc:/ui/modules/Linphone/Notifications/ReceivedMessageNotification.qml"
#define QML_NOTIFICATION_PATH_RECEIVED_MESSAGE "qrc:/ui/modules/Linphone/Notifications/NotificationReceivedMessage.qml"
#define QML_NOTIFICATION_PATH_RECEIVED_FILE_MESSAGE "qrc:/ui/modules/Linphone/Notifications/NotificationReceivedFileMessage.qml"
#define QML_NOTIFICATION_PATH_RECEIVED_CALL "qrc:/ui/modules/Linphone/Notifications/NotificationReceivedCall.qml"
#define NOTIFICATION_TIMEOUT_RECEIVED_MESSAGE 10000
#define NOTIFICATION_TIMEOUT_RECEIVED_FILE_MESSAGE 10000
#define NOTIFICATION_TIMEOUT_RECEIVED_CALL 10000
// Arbitrary hardcoded values.
#define NOTIFICATION_SPACING 10
......@@ -77,22 +85,22 @@ Notifier::Notifier (QObject *parent) :
QQmlEngine *engine = App::getInstance()->getEngine();
// Build components.
m_components[Notifier::Call] = new QQmlComponent(engine, QUrl(QML_CALL_NOTIFICATION_PATH));
m_components[Notifier::MessageReceived] = new QQmlComponent(engine, QUrl(QML_MESSAGE_RECEIVED_NOTIFICATION_PATH));
m_components[Notifier::MessageReceived] = new QQmlComponent(engine, QUrl(QML_NOTIFICATION_PATH_RECEIVED_MESSAGE));
m_components[Notifier::FileMessageReceived] = new QQmlComponent(engine, QUrl(QML_NOTIFICATION_PATH_RECEIVED_FILE_MESSAGE));
m_components[Notifier::CallReceived] = new QQmlComponent(engine, QUrl(QML_NOTIFICATION_PATH_RECEIVED_CALL));
// Check errors.
for (int i = 0; i < Notifier::MaxNbTypes; ++i) {
QQmlComponent *component = m_components[i];
if (component->isError()) {
qWarning() << QStringLiteral("Errors found in `Notification` component %1:").arg(i) <<
component->errors();
qWarning() << QStringLiteral("Errors found in `Notification` component %1:").arg(i) << component->errors();
abort();
}
}
}
Notifier::~Notifier () {
for (int i = 0; i < Notifier::MaxNbTypes; i++)
for (int i = 0; i < Notifier::MaxNbTypes; ++i)
delete m_components[i];
}
......@@ -110,9 +118,9 @@ QObject *Notifier::createNotification (Notifier::NotificationType type) {
// Create instance and set attributes.
QObject *object = m_components[type]->create();
int offset = getNotificationSize(*object, NOTIFICATION_HEIGHT_PROPERTY);
int offset = getNotificationSize(*object, NOTIFICATION_PROPERTY_HEIGHT);
if (offset == -1 || !::setProperty(*object, NOTIFICATION_OFFSET_PROPERTY_NAME, m_offset)) {
if (offset == -1 || !::setProperty(*object, NOTIFICATION_PROPERTY_OFFSET, m_offset)) {
delete object;
m_mutex.unlock();
return nullptr;
......@@ -149,7 +157,7 @@ void Notifier::showNotification (QObject *notification, int timeout) {
qInfo() << "Update notifications counter, hidden notification detected.";
if (visible)
qFatal("A notification cannot be visible twice!");
qWarning("A notification cannot be visible twice!");
m_mutex.lock();
......@@ -172,20 +180,41 @@ void Notifier::showNotification (QObject *notification, int timeout) {
// -----------------------------------------------------------------------------
void Notifier::notifyReceivedMessage (
int timeout,
const shared_ptr<linphone::ChatRoom> &room,
const shared_ptr<linphone::ChatMessage> &message
) {
QObject *object = createNotification(Notifier::MessageReceived);
void Notifier::notifyReceivedMessage (const shared_ptr<linphone::ChatMessage> &message) {
QObject *notification = createNotification(Notifier::MessageReceived);
if (!notification)
return;
QVariantMap map;
map["message"] = ::Utils::linphoneStringToQString(message->getText());
map["sipAddress"] = ::Utils::linphoneStringToQString(message->getFromAddress()->asStringUriOnly());
map["window"].setValue(App::getInstance()->getMainWindow());
if (object)
showNotification(object, timeout);
::setProperty(*notification, NOTIFICATION_PROPERTY_DATA, map);
showNotification(notification, NOTIFICATION_TIMEOUT_RECEIVED_MESSAGE);
}
void Notifier::showCallMessage (int timeout, const QString &) {
QObject *object = createNotification(Notifier::Call);
void Notifier::notifyReceivedFileMessage (const shared_ptr<linphone::ChatMessage> &message) {
QObject *notification = createNotification(Notifier::FileMessageReceived);
if (!notification)
return;
QVariantMap map;
map["fileUri"] = ::Utils::linphoneStringToQString(message->getFileTransferFilepath());
map["fileSize"] = static_cast<quint64>(message->getFileTransferInformation()->getSize());
::setProperty(*notification, NOTIFICATION_PROPERTY_DATA, map);
showNotification(notification, NOTIFICATION_TIMEOUT_RECEIVED_FILE_MESSAGE);
}
void Notifier::notifyReceivedCall (const shared_ptr<linphone::Call> &call) {
QObject *notification = createNotification(Notifier::CallReceived);
if (!notification)
return;
QVariantMap map;
map["call"].setValue(CoreManager::getInstance()->getCallsListModel()->getCall(call));
if (object)
showNotification(object, timeout);
::setProperty(*notification, NOTIFICATION_PROPERTY_DATA, map);
showNotification(notification, NOTIFICATION_TIMEOUT_RECEIVED_CALL);
}
......@@ -40,19 +40,15 @@ public:
~Notifier ();
enum NotificationType {
Call,
MessageReceived,
FileMessageReceived,
CallReceived,
MaxNbTypes
};
void notifyReceivedMessage (
int timeout,
const std::shared_ptr<linphone::ChatRoom> &room,
const std::shared_ptr<linphone::ChatMessage> &message
);
// TODO
void showCallMessage (int timeout, const QString &);
void notifyReceivedMessage (const std::shared_ptr<linphone::ChatMessage> &message);
void notifyReceivedFileMessage (const std::shared_ptr<linphone::ChatMessage> &message);
void notifyReceivedCall (const std::shared_ptr<linphone::Call> &call);
private:
QObject *createNotification (NotificationType type);
......
......@@ -28,6 +28,8 @@
int main (int argc, char *argv[]) {
Logger::init();
QCoreApplication::setAttribute(Qt::AA_UseOpenGLES, true);
// Force shader version 2.0.
QSurfaceFormat fmt;
fmt.setVersion(2, 0);
......
......@@ -77,7 +77,10 @@ Item {
to: 'opened'
ScriptAction {
script: popup.showNormal()
script: {
popup.showNormal()
popup.requestActivate()
}
}
NumberAnimation {
......
......@@ -23,8 +23,10 @@ Item {
iconSize: MessagesCounterStyle.iconSize.message
Icon {
anchors.horizontalCenter: parent.right
anchors.verticalCenter: parent.bottom
anchors {
horizontalCenter: parent.right
verticalCenter: parent.bottom
}
icon: 'chat_amount'
iconSize: MessagesCounterStyle.iconSize.amount
......
import QtQuick 2.7
// =============================================================================
Notification {
Rectangle {
color: 'red'
width: 200
height: 100
}
}
......@@ -15,15 +15,19 @@ DesktopPopup {
// ---------------------------------------------------------------------------
property int notificationOffset: 0
property alias notificationHeight: notification.popupHeight
property int notificationOffset: 0
property var notificationData: null
readonly property var window: _window
property var _window
// ---------------------------------------------------------------------------
flags: Qt.Popup
Component.onCompleted: {
var window = data[0]
var window = _window = data[0]
Utils.assert(
Utils.qmlTypeof(window, 'QQuickWindowQmlImpl'), true,
......@@ -45,7 +49,7 @@ DesktopPopup {
}
var height = screen.desktopAvailableHeight - window.height
return height - notificationOffset % height
return height - (notificationOffset % height)
})
}
}
......@@ -11,6 +11,10 @@ TestCase {
id: notification
}
function test_notificationDataProperty () {
compare(Utils.isObject(notification.notificationData), true)
}
function test_notificationHeightProperty () {
compare(Utils.isInteger(notification.notificationHeight), true)
}
......
import QtQuick 2.7
import QtQuick.Layouts 1.3
import Common 1.0
import Linphone 1.0
import Linphone.Styles 1.0
// =============================================================================
Notification {
id: notification
// ---------------------------------------------------------------------------
property var _call: notificationData && notificationData.call
property var _contact: _contactObserver.contact
property var _contactObserver: SipAddressesModel.getContactObserver(_call ? _call.sipAddress : '')
// ---------------------------------------------------------------------------
function _close (cb) {
notification.window.setVisible(false)
cb()
}
// ---------------------------------------------------------------------------
Rectangle {
color: NotificationReceivedCallStyle.color
height: NotificationReceivedCallStyle.height
width: NotificationReceivedCallStyle.width
Icon {
anchors {
left: parent.left
top: parent.top
}
icon: 'call_sign_incoming'
iconSize: NotificationReceivedCallStyle.iconSize
}
Loader {
active: notification._call
anchors {
fill: parent
leftMargin: NotificationReceivedCallStyle.leftMargin
rightMargin: NotificationReceivedCallStyle.rightMargin
bottomMargin: NotificationReceivedCallStyle.bottomMargin
}
sourceComponent: ColumnLayout {
spacing: NotificationReceivedCallStyle.spacing
Contact {
Layout.fillWidth: true
entry: ({
contact: notification._contact,
sipAddress: notification._contactObserver.sipAddress
})
}
// ---------------------------------------------------------------------
// Action buttons.
// ---------------------------------------------------------------------
Item {
Layout.fillHeight: true
Layout.fillWidth: true
ActionBar {
anchors.centerIn: parent
iconSize: NotificationReceivedCallStyle.actionArea.iconSize
ActionButton {
icon: 'video_call_accept'
onClicked: notification._close(notification._call.acceptWithVideo)
}
ActionButton {
icon: 'call_accept'
onClicked: notification._close(notification._call.accept)
}
}
ActionBar {
anchors {
right: parent.right
rightMargin: NotificationReceivedCallStyle.actionArea.rightButtonsGroupMargin
verticalCenter: parent.verticalCenter
}
iconSize: NotificationReceivedCallStyle.actionArea.iconSize
ActionButton {
icon: 'hangup'
onClicked: notification._close(notification._call.terminate)
}
}
}
}
}
}
}
import QtQuick 2.7
import QtQuick.Layouts 1.3
import Common 1.0
import Linphone 1.0
import Linphone.Styles 1.0
import Utils 1.0
// =============================================================================
Notification {
id: notification
// ---------------------------------------------------------------------------
property string _fileUri: notificationData ? notificationData.fileUri : ''
// ---------------------------------------------------------------------------
Rectangle {
color: NotificationReceivedFileMessageStyle.color
height: NotificationReceivedFileMessageStyle.height
width: NotificationReceivedFileMessageStyle.width
Icon {
anchors {
left: parent.left
top: parent.top
}
icon: 'file_sign'
iconSize: NotificationReceivedFileMessageStyle.iconSize
}
Loader {
active: notification._fileUri.length > 0
anchors {
fill: parent
leftMargin: NotificationReceivedFileMessageStyle.leftMargin
rightMargin: NotificationReceivedFileMessageStyle.rightMargin
}
sourceComponent: RowLayout {
anchors.fill: parent
spacing: NotificationReceivedFileMessageStyle.spacing
Text {
Layout.fillWidth: true
color: NotificationReceivedFileMessageStyle.fileName.color
elide: Text.ElideRight
font.pointSize: NotificationReceivedFileMessageStyle.fileName.fontSize
text: Utils.basename(notification._fileUri)
}
Text {
Layout.preferredWidth: NotificationReceivedFileMessageStyle.fileSize.width
color: NotificationReceivedFileMessageStyle.fileSize.color
elide: Text.ElideRight
font.pointSize: NotificationReceivedFileMessageStyle.fileSize.fontSize
horizontalAlignment: Text.AlignRight
text: Utils.formatSize(notification.notificationData.fileSize)
}
}
MouseArea {
anchors.fill: parent
cursorShape: containsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor
hoverEnabled: true
onClicked: {
notification.window.setVisible(false)
Qt.openUrlExternally('file://' + Utils.dirname(notification._fileUri))
}
}
}
}
}
import QtQuick 2.7
import QtQuick.Layouts 1.3
import Common 1.0
import Linphone 1.0
import Linphone.Styles 1.0
// =============================================================================
Notification {
id: notification
// ---------------------------------------------------------------------------
property string _sipAddress: notificationData ? notificationData.sipAddress : ''
property var _contact: _contactObserver.contact
property var _contactObserver: SipAddressesModel.getContactObserver(_sipAddress)
// ---------------------------------------------------------------------------
Rectangle {
color: NotificationReceivedMessageStyle.color
height: NotificationReceivedMessageStyle.height
width: NotificationReceivedMessageStyle.width
Icon {
anchors {
left: parent.left
top: parent.top
}
icon: 'message_sign'
iconSize: NotificationReceivedMessageStyle.iconSize
}
Loader {
active: notification._sipAddress.length > 0
anchors {
fill: parent
leftMargin: NotificationReceivedMessageStyle.leftMargin
rightMargin: NotificationReceivedMessageStyle.rightMargin
bottomMargin: NotificationReceivedMessageStyle.bottomMargin
}
sourceComponent: ColumnLayout {
spacing: NotificationReceivedMessageStyle.spacing
Contact {
Layout.fillWidth: true
entry: ({
contact: notification._contact,
sipAddress: notification._sipAddress
})
}
Rectangle {
Layout.fillHeight: true
Layout.fillWidth: true
color: NotificationReceivedMessageStyle.messageContainer.color
radius: NotificationReceivedMessageStyle.messageContainer.radius
Text {
anchors {
fill: parent
margins: NotificationReceivedMessageStyle.messageContainer.margins
}
color: NotificationReceivedMessageStyle.messageContainer.text.color
elide: Text.ElideRight
font {
italic: true
pointSize: NotificationReceivedMessageStyle.messageContainer.text.fontSize
}
verticalAlignment: Text.AlignVCenter
text: notification.notificationData.message
wrapMode: Text.Wrap
}
}
}
}
MouseArea {
anchors.fill: parent
cursorShape: containsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor
hoverEnabled: true
onClicked: {
notification.window.setVisible(false)
notification.notificationData.window.setView('Conversation', {
sipAddress: notification._sipAddress
})
}
}
}
}
import QtQuick 2.7
// =============================================================================
Notification {
Rectangle {
color: 'red'
width: 200
height: 100
}
}
pragma Singleton
import QtQuick 2.7
import Common 1.0
// =============================================================================
QtObject {
property color color: Colors.k
property int height: 120
property int iconSize: 40
property int spacing: 0
property int width: 300
property int bottomMargin: 15
property int leftMargin: 15
property int rightMargin: 15
property QtObject actionArea: QtObject {
property int iconSize: 40
property int rightButtonsGroupMargin: 15
}
}
pragma Singleton
import QtQuick 2.7
import Common 1.0
// =============================================================================
QtObject {
property color color: Colors.k
property int height: 55
property int iconSize: 40
property int leftMargin: 25
property int rightMargin: 15
property int spacing: 10
property int width: 300
property QtObject fileName: QtObject {
property color color: Colors.h
property int fontSize: 10
}
property QtObject fileSize: QtObject {
property color color: Colors.h
property int fontSize: 9
property int width: 100
}
}
pragma Singleton
import QtQuick 2.7
import Common 1.0
// =============================================================================
QtObject {
property color color: Colors.k
property int bottomMargin: 15
property int iconSize: 40
property int leftMargin: 15
property int rightMargin: 15
property int spacing: 0
property int width: 300
property int height: 120
property QtObject messageContainer: QtObject {
property color color: Colors.m
property int radius: 6
property int margins: 10
property QtObject text: QtObject {
property color color: Colors.l
property int fontSize: 9
}
}
}
......@@ -4,5 +4,5 @@ import QtQuick 2.7
// =============================================================================
QtObject {
property int margin: 10
property int margin: 0
}
......@@ -16,7 +16,10 @@ singleton ContactDescriptionStyle 1.0 Contact/ContactDescriptionStyle.qml
singleton ContactStyle 1.0 Contact/ContactStyle.qml
singleton MessagesCounterStyle 1.0 Contact/MessagesCounterStyle.qml
singleton NotificationStyle 1.0 NotificationStyle.qml
singleton NotificationStyle 1.0 Notifications/NotificationStyle.qml
singleton NotificationReceivedCallStyle 1.0 Notifications/NotificationReceivedCallStyle.qml
singleton NotificationReceivedMessageStyle 1.0 Notifications/NotificationReceivedMessageStyle.qml
singleton NotificationReceivedFileMessageStyle 1.0 Notifications/NotificationReceivedFileMessageStyle.qml
singleton PresenceStringStyle 1.0 Presence/PresenceStringStyle.qml
......
......@@ -261,6 +261,18 @@ function assert (condition, message) {
// -----------------------------------------------------------------------------
function basename (str) {
return str.slice(str.lastIndexOf('/') + 1)
}
// -----------------------------------------------------------------------------
function dirname (str) {
return str.slice(0, str.lastIndexOf('/') + 1)
}
// -----------------------------------------------------------------------------
function extractProperties (obj, pattern) {
if (!pattern) {
return {}
......
......@@ -46,10 +46,6 @@ ApplicationWindow {
})
}
function ensureCollapsed () {
collapse.setCollapsed(true)
}
// ---------------------------------------------------------------------------
function _updateSelectedEntry (view, props) {
......@@ -66,6 +62,10 @@ ApplicationWindow {
}
function _setView (view, props) {
window.showNormal()
window.requestActivate()
collapse.setCollapsed(true)
_updateSelectedEntry(view, props)
_currentView = view
contentLoader.setSource(view + '.qml', props || {})
......@@ -153,31 +153,23 @@ ApplicationWindow {
model: SmartSearchBarModel {}
onAddContact: {
window.ensureCollapsed()
window.setView('ContactEdit', {
onAddContact: window.setView('ContactEdit', {
sipAddress: sipAddress
})
}
onLaunchCall: CallsListModel.launchAudioCall(sipAddress)
onLaunchChat: {
window.ensureCollapsed()
window.setView('Conversation', {
onLaunchChat: window.setView('Conversation', {
sipAddress: sipAddress
})
}
onLaunchVideoCall: CallsListModel.launchVideoCall(sipAddress)
onEntryClicked: {
window.ensureCollapsed()
window.setView(entry.contact ? 'ContactEdit' : 'Conversation', {
onEntryClicked: window.setView(entry.contact ? 'ContactEdit' : 'Conversation', {
sipAddress: entry.sipAddress
})
}
}
}
}
// ---------------------------------------------------------------------------
// Content.
......
cmake-builder @ 326a0976
Subproject commit a79e2826e056cc48b3b4d0eda4f38d82f124bb56
Subproject commit 326a0976c0b42927056d39d99a396a2d0a8fc3da
linphone @ 2c3f66ef
Subproject commit 87bc9f7ea55f8e449cf1d6b83fefacd2d9e596b0
Subproject commit 2c3f66ef6f160f4c23efc2dea9485ddae8194af1
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