mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-05-02 18:36:24 +00:00
feat(ui/modules/Linphone/Timeline): display messages counter if necessary
This commit is contained in:
parent
79853f9995
commit
bd47b42141
15 changed files with 216 additions and 87 deletions
18
tests/assets/images/chat_amount.svg
Normal file
18
tests/assets/images/chat_amount.svg
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!-- Generator: Sketch 40.3 (33839) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title>statut_avatar_busy_l</title>
|
||||||
|
<desc>Created with Sketch.</desc>
|
||||||
|
<defs>
|
||||||
|
<path d="M7.9995,16 C3.581,16 0,12.4185 0,8 C0,3.582 3.581,0 7.9995,0 C12.418,0 16,3.582 16,8 C16,12.4185 12.418,16 7.9995,16 Z" id="path-1"></path>
|
||||||
|
<mask id="mask-2" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="16" height="16" fill="white">
|
||||||
|
<use xlink:href="#path-1"></use>
|
||||||
|
</mask>
|
||||||
|
</defs>
|
||||||
|
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g id="statut_avatar_busy_l">
|
||||||
|
<path d="M7.9995,16 C3.581,16 0,12.4185 0,8 C0,3.582 3.581,0 7.9995,0 C12.418,0 16,3.582 16,8 C16,12.4185 12.418,16 7.9995,16 Z" id="statut_avatar_busy_s" fill="#FF5E00"></path>
|
||||||
|
<use id="statut_avatar_busy_s" stroke="#00FFFFFF" mask="url(#mask-2)" stroke-width="4" xlink:href="#path-1"></use>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
14
tests/assets/images/chat_count.svg
Normal file
14
tests/assets/images/chat_count.svg
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="18px" height="18px" viewBox="0 0 18 18" 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>chat_count</title>
|
||||||
|
<desc>Created with Sketch.</desc>
|
||||||
|
<defs></defs>
|
||||||
|
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<g id="chat_count" stroke="#96A6B1">
|
||||||
|
<path d="M6.40657699,14.958235 C6.4063782,14.958235 4.02960743,17.4749743 1,16.7980486 C1,16.7980486 3.96659001,15.9311541 3.29347644,13.3085893 L3.27180799,13.1872479 C1.86653929,11.8936694 1,10.1230801 1,8.16948422 C1,4.20997633 4.5607827,1 8.95192433,1 C13.3432648,1 16.9036499,4.20997633 16.9036499,8.16948422 C16.9036499,12.1289921 13.3432648,15.3387695 8.95192433,15.3387695 C8.06133107,15.3387695 7.20552661,15.2072832 6.4061794,14.9638048 L6.40657699,14.958235 L6.40657699,14.958235 Z" stroke-width="1.5"></path>
|
||||||
|
<path d="M12.2018249,9.5 L5.70182494,9.5"></path>
|
||||||
|
<path d="M12.2018249,7.5 L5.70182494,7.5"></path>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
|
|
@ -24,6 +24,8 @@
|
||||||
<file>assets/images/camera_on_hovered.svg</file>
|
<file>assets/images/camera_on_hovered.svg</file>
|
||||||
<file>assets/images/camera_on_normal.svg</file>
|
<file>assets/images/camera_on_normal.svg</file>
|
||||||
<file>assets/images/camera_on_pressed.svg</file>
|
<file>assets/images/camera_on_pressed.svg</file>
|
||||||
|
<file>assets/images/chat_amount.svg</file>
|
||||||
|
<file>assets/images/chat_count.svg</file>
|
||||||
<file>assets/images/chat_error.svg</file>
|
<file>assets/images/chat_error.svg</file>
|
||||||
<file>assets/images/chat_hovered.svg</file>
|
<file>assets/images/chat_hovered.svg</file>
|
||||||
<file>assets/images/chat_normal.svg</file>
|
<file>assets/images/chat_normal.svg</file>
|
||||||
|
|
@ -208,6 +210,7 @@
|
||||||
<file>ui/modules/Linphone/Contact/Avatar.qml</file>
|
<file>ui/modules/Linphone/Contact/Avatar.qml</file>
|
||||||
<file>ui/modules/Linphone/Contact/ContactDescription.qml</file>
|
<file>ui/modules/Linphone/Contact/ContactDescription.qml</file>
|
||||||
<file>ui/modules/Linphone/Contact/Contact.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/CallNotification.qml</file>
|
||||||
<file>ui/modules/Linphone/Notifications/Notification.qml</file>
|
<file>ui/modules/Linphone/Notifications/Notification.qml</file>
|
||||||
<file>ui/modules/Linphone/Notifications/ReceivedMessageNotification.qml</file>
|
<file>ui/modules/Linphone/Notifications/ReceivedMessageNotification.qml</file>
|
||||||
|
|
@ -220,6 +223,7 @@
|
||||||
<file>ui/modules/Linphone/Styles/Contact/AvatarStyle.qml</file>
|
<file>ui/modules/Linphone/Styles/Contact/AvatarStyle.qml</file>
|
||||||
<file>ui/modules/Linphone/Styles/Contact/ContactDescriptionStyle.qml</file>
|
<file>ui/modules/Linphone/Styles/Contact/ContactDescriptionStyle.qml</file>
|
||||||
<file>ui/modules/Linphone/Styles/Contact/ContactStyle.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/NotificationStyle.qml</file>
|
||||||
<file>ui/modules/Linphone/Styles/Presence/PresenceStringStyle.qml</file>
|
<file>ui/modules/Linphone/Styles/Presence/PresenceStringStyle.qml</file>
|
||||||
<file>ui/modules/Linphone/Styles/qmldir</file>
|
<file>ui/modules/Linphone/Styles/qmldir</file>
|
||||||
|
|
|
||||||
|
|
@ -78,11 +78,11 @@ ChatModel::ChatModel (QObject *parent) : QAbstractListModel(parent) {
|
||||||
CoreManager::getInstance()->getSipAddressesModel()->connectToChatModel(this);
|
CoreManager::getInstance()->getSipAddressesModel()->connectToChatModel(this);
|
||||||
|
|
||||||
QObject::connect(
|
QObject::connect(
|
||||||
&(*m_core_handlers), &CoreHandlers::receivedMessage,
|
&(*m_core_handlers), &CoreHandlers::messageReceived,
|
||||||
this, [this](const shared_ptr<linphone::ChatMessage> &message) {
|
this, [this](const shared_ptr<linphone::ChatMessage> &message) {
|
||||||
if (m_chat_room == message->getChatRoom()) {
|
if (m_chat_room == message->getChatRoom()) {
|
||||||
insertMessageAtEnd(message);
|
insertMessageAtEnd(message);
|
||||||
m_chat_room->markAsRead();
|
resetMessagesCount();
|
||||||
|
|
||||||
emit messageReceived(message);
|
emit messageReceived(message);
|
||||||
}
|
}
|
||||||
|
|
@ -165,10 +165,11 @@ void ChatModel::setSipAddress (const QString &sip_address) {
|
||||||
m_entries.clear();
|
m_entries.clear();
|
||||||
|
|
||||||
shared_ptr<linphone::Core> core = CoreManager::getInstance()->getCore();
|
shared_ptr<linphone::Core> core = CoreManager::getInstance()->getCore();
|
||||||
string std_sip_address = ::Utils::qStringToLinphoneString(sip_address);
|
|
||||||
|
|
||||||
m_chat_room = core->getChatRoomFromUri(std_sip_address);
|
m_chat_room = core->getChatRoomFromUri(::Utils::qStringToLinphoneString(sip_address));
|
||||||
m_chat_room->markAsRead();
|
|
||||||
|
if (m_chat_room->getUnreadMessagesCount() > 0)
|
||||||
|
resetMessagesCount();
|
||||||
|
|
||||||
// Get messages.
|
// Get messages.
|
||||||
for (auto &message : m_chat_room->getHistory(0)) {
|
for (auto &message : m_chat_room->getHistory(0)) {
|
||||||
|
|
@ -336,3 +337,8 @@ void ChatModel::insertMessageAtEnd (const shared_ptr<linphone::ChatMessage> &mes
|
||||||
|
|
||||||
endInsertRows();
|
endInsertRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChatModel::resetMessagesCount () {
|
||||||
|
m_chat_room->markAsRead();
|
||||||
|
emit messagesCountReset();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,8 @@ signals:
|
||||||
void messageSent (const std::shared_ptr<linphone::ChatMessage> &message);
|
void messageSent (const std::shared_ptr<linphone::ChatMessage> &message);
|
||||||
void messageReceived (const std::shared_ptr<linphone::ChatMessage> &message);
|
void messageReceived (const std::shared_ptr<linphone::ChatMessage> &message);
|
||||||
|
|
||||||
|
void messagesCountReset ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void fillMessageEntry (
|
void fillMessageEntry (
|
||||||
QVariantMap &dest,
|
QVariantMap &dest,
|
||||||
|
|
@ -95,6 +97,8 @@ private:
|
||||||
|
|
||||||
void insertMessageAtEnd (const std::shared_ptr<linphone::ChatMessage> &message);
|
void insertMessageAtEnd (const std::shared_ptr<linphone::ChatMessage> &message);
|
||||||
|
|
||||||
|
void resetMessagesCount ();
|
||||||
|
|
||||||
QList<ChatEntryData> m_entries;
|
QList<ChatEntryData> m_entries;
|
||||||
std::shared_ptr<linphone::ChatRoom> m_chat_room;
|
std::shared_ptr<linphone::ChatRoom> m_chat_room;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,33 +2,48 @@
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
ChatModelFilter::ChatModelFilter (QObject *parent) : QSortFilterProxyModel(parent) {
|
// Fetch the L last filtered chat entries.
|
||||||
setSourceModel(&m_chat_model);
|
class ChatProxyModel::ChatModelFilter : public QSortFilterProxyModel {
|
||||||
}
|
public:
|
||||||
|
ChatModelFilter (QObject *parent) : QSortFilterProxyModel(parent) {
|
||||||
|
setSourceModel(&m_chat_model);
|
||||||
|
}
|
||||||
|
|
||||||
bool ChatModelFilter::filterAcceptsRow (int source_row, const QModelIndex &) const {
|
ChatModel::EntryType getEntryTypeFilter () {
|
||||||
if (m_entry_type_filter == ChatModel::EntryType::GenericEntry)
|
return m_entry_type_filter;
|
||||||
return true;
|
}
|
||||||
|
|
||||||
QModelIndex index = sourceModel()->index(source_row, 0, QModelIndex());
|
void setEntryTypeFilter (ChatModel::EntryType type) {
|
||||||
const QVariantMap &data = index.data().toMap();
|
m_entry_type_filter = type;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
return data["type"].toInt() == m_entry_type_filter;
|
protected:
|
||||||
}
|
bool filterAcceptsRow (int source_row, const QModelIndex &) const override {
|
||||||
|
if (m_entry_type_filter == ChatModel::EntryType::GenericEntry)
|
||||||
|
return true;
|
||||||
|
|
||||||
void ChatModelFilter::setEntryTypeFilter (ChatModel::EntryType type) {
|
QModelIndex index = sourceModel()->index(source_row, 0, QModelIndex());
|
||||||
m_entry_type_filter = type;
|
const QVariantMap &data = index.data().toMap();
|
||||||
invalidate();
|
|
||||||
}
|
return data["type"].toInt() == m_entry_type_filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ChatModel m_chat_model;
|
||||||
|
ChatModel::EntryType m_entry_type_filter = ChatModel::EntryType::GenericEntry;
|
||||||
|
};
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
const unsigned int ChatProxyModel::ENTRIES_CHUNK_SIZE = 50;
|
const unsigned int ChatProxyModel::ENTRIES_CHUNK_SIZE = 50;
|
||||||
|
|
||||||
ChatProxyModel::ChatProxyModel (QObject *parent) : QSortFilterProxyModel(parent) {
|
ChatProxyModel::ChatProxyModel (QObject *parent) : QSortFilterProxyModel(parent) {
|
||||||
setSourceModel(&m_chat_model_filter);
|
m_chat_model_filter = new ChatModelFilter(this);
|
||||||
|
|
||||||
ChatModel *chat = static_cast<ChatModel *>(m_chat_model_filter.sourceModel());
|
setSourceModel(m_chat_model_filter);
|
||||||
|
|
||||||
|
ChatModel *chat = static_cast<ChatModel *>(m_chat_model_filter->sourceModel());
|
||||||
|
|
||||||
QObject::connect(
|
QObject::connect(
|
||||||
chat, &ChatModel::messageReceived, this, [this](const shared_ptr<linphone::ChatMessage> &) {
|
chat, &ChatModel::messageReceived, this, [this](const shared_ptr<linphone::ChatMessage> &) {
|
||||||
|
|
@ -45,7 +60,7 @@ ChatProxyModel::ChatProxyModel (QObject *parent) : QSortFilterProxyModel(parent)
|
||||||
|
|
||||||
void ChatProxyModel::loadMoreEntries () {
|
void ChatProxyModel::loadMoreEntries () {
|
||||||
int count = rowCount();
|
int count = rowCount();
|
||||||
int parent_count = m_chat_model_filter.rowCount();
|
int parent_count = m_chat_model_filter->rowCount();
|
||||||
|
|
||||||
if (count < parent_count) {
|
if (count < parent_count) {
|
||||||
// Do not increase `m_n_max_displayed_entries` if it's not necessary...
|
// Do not increase `m_n_max_displayed_entries` if it's not necessary...
|
||||||
|
|
@ -62,19 +77,37 @@ void ChatProxyModel::loadMoreEntries () {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatProxyModel::setEntryTypeFilter (ChatModel::EntryType type) {
|
void ChatProxyModel::setEntryTypeFilter (ChatModel::EntryType type) {
|
||||||
if (m_chat_model_filter.getEntryTypeFilter() != type) {
|
if (m_chat_model_filter->getEntryTypeFilter() != type) {
|
||||||
m_chat_model_filter.setEntryTypeFilter(type);
|
m_chat_model_filter->setEntryTypeFilter(type);
|
||||||
emit entryTypeFilterChanged(type);
|
emit entryTypeFilterChanged(type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatProxyModel::removeEntry (int id) {
|
void ChatProxyModel::removeEntry (int id) {
|
||||||
QModelIndex source_index = mapToSource(index(id, 0));
|
QModelIndex source_index = mapToSource(index(id, 0));
|
||||||
static_cast<ChatModel *>(m_chat_model_filter.sourceModel())->removeEntry(
|
static_cast<ChatModel *>(m_chat_model_filter->sourceModel())->removeEntry(
|
||||||
m_chat_model_filter.mapToSource(source_index).row()
|
m_chat_model_filter->mapToSource(source_index).row()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChatProxyModel::filterAcceptsRow (int source_row, const QModelIndex &) const {
|
void ChatProxyModel::removeAllEntries () {
|
||||||
return m_chat_model_filter.rowCount() - source_row <= m_n_max_displayed_entries;
|
static_cast<ChatModel *>(m_chat_model_filter->sourceModel())->removeAllEntries();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatProxyModel::sendMessage (const QString &message) {
|
||||||
|
static_cast<ChatModel *>(m_chat_model_filter->sourceModel())->sendMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ChatProxyModel::filterAcceptsRow (int source_row, const QModelIndex &) const {
|
||||||
|
return m_chat_model_filter->rowCount() - source_row <= m_n_max_displayed_entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ChatProxyModel::getSipAddress () const {
|
||||||
|
return static_cast<ChatModel *>(m_chat_model_filter->sourceModel())->getSipAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatProxyModel::setSipAddress (const QString &sip_address) {
|
||||||
|
static_cast<ChatModel *>(m_chat_model_filter->sourceModel())->setSipAddress(
|
||||||
|
sip_address
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,35 +5,11 @@
|
||||||
|
|
||||||
#include "ChatModel.hpp"
|
#include "ChatModel.hpp"
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
// Fetch the L last filtered chat entries.
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
// Cannot be used as a nested class by Qt and `Q_OBJECT` macro
|
|
||||||
// must be used in header c++ file.
|
|
||||||
class ChatModelFilter : public QSortFilterProxyModel {
|
|
||||||
Q_OBJECT;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ChatModelFilter (QObject *parent = Q_NULLPTR);
|
|
||||||
|
|
||||||
ChatModel::EntryType getEntryTypeFilter () {
|
|
||||||
return m_entry_type_filter;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setEntryTypeFilter (ChatModel::EntryType type);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool filterAcceptsRow (int source_row, const QModelIndex &parent) const override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
ChatModel m_chat_model;
|
|
||||||
ChatModel::EntryType m_entry_type_filter = ChatModel::EntryType::GenericEntry;
|
|
||||||
};
|
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
class ChatProxyModel : public QSortFilterProxyModel {
|
class ChatProxyModel : public QSortFilterProxyModel {
|
||||||
|
class ChatModelFilter;
|
||||||
|
|
||||||
Q_OBJECT;
|
Q_OBJECT;
|
||||||
|
|
||||||
Q_PROPERTY(
|
Q_PROPERTY(
|
||||||
|
|
@ -50,16 +26,12 @@ public:
|
||||||
Q_INVOKABLE void setEntryTypeFilter (ChatModel::EntryType type);
|
Q_INVOKABLE void setEntryTypeFilter (ChatModel::EntryType type);
|
||||||
Q_INVOKABLE void removeEntry (int id);
|
Q_INVOKABLE void removeEntry (int id);
|
||||||
|
|
||||||
Q_INVOKABLE void removeAllEntries () {
|
Q_INVOKABLE void removeAllEntries ();
|
||||||
static_cast<ChatModel *>(m_chat_model_filter.sourceModel())->removeAllEntries();
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_INVOKABLE void sendMessage (const QString &message) {
|
Q_INVOKABLE void sendMessage (const QString &message);
|
||||||
static_cast<ChatModel *>(m_chat_model_filter.sourceModel())->sendMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void sipAddressChanged (const QString &sipAddress);
|
void sipAddressChanged (const QString &sip_address);
|
||||||
void moreEntriesLoaded (int n);
|
void moreEntriesLoaded (int n);
|
||||||
|
|
||||||
void entryTypeFilterChanged (ChatModel::EntryType type);
|
void entryTypeFilterChanged (ChatModel::EntryType type);
|
||||||
|
|
@ -68,17 +40,10 @@ protected:
|
||||||
bool filterAcceptsRow (int source_row, const QModelIndex &source_parent) const override;
|
bool filterAcceptsRow (int source_row, const QModelIndex &source_parent) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString getSipAddress () const {
|
QString getSipAddress () const;
|
||||||
return static_cast<ChatModel *>(m_chat_model_filter.sourceModel())->getSipAddress();
|
void setSipAddress (const QString &sip_address);
|
||||||
}
|
|
||||||
|
|
||||||
void setSipAddress (const QString &sip_address) {
|
ChatModelFilter *m_chat_model_filter;
|
||||||
static_cast<ChatModel *>(m_chat_model_filter.sourceModel())->setSipAddress(
|
|
||||||
sip_address
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatModelFilter m_chat_model_filter;
|
|
||||||
int m_n_max_displayed_entries = ENTRIES_CHUNK_SIZE;
|
int m_n_max_displayed_entries = ENTRIES_CHUNK_SIZE;
|
||||||
|
|
||||||
static const unsigned int ENTRIES_CHUNK_SIZE;
|
static const unsigned int ENTRIES_CHUNK_SIZE;
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ void CoreHandlers::onMessageReceived (
|
||||||
const shared_ptr<linphone::ChatRoom> &room,
|
const shared_ptr<linphone::ChatRoom> &room,
|
||||||
const shared_ptr<linphone::ChatMessage> &message
|
const shared_ptr<linphone::ChatMessage> &message
|
||||||
) {
|
) {
|
||||||
emit receivedMessage(message);
|
emit messageReceived(message);
|
||||||
|
|
||||||
const App *app = App::getInstance();
|
const App *app = App::getInstance();
|
||||||
if (!app->hasFocus())
|
if (!app->hasFocus())
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ class CoreHandlers :
|
||||||
Q_OBJECT;
|
Q_OBJECT;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void receivedMessage (const std::shared_ptr<linphone::ChatMessage> &message);
|
void messageReceived (const std::shared_ptr<linphone::ChatMessage> &message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void onAuthenticationRequested (
|
void onAuthenticationRequested (
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ SipAddressesModel::SipAddressesModel (QObject *parent) : QAbstractListModel(pare
|
||||||
|
|
||||||
m_handlers = CoreManager::getInstance()->getHandlers();
|
m_handlers = CoreManager::getInstance()->getHandlers();
|
||||||
QObject::connect(
|
QObject::connect(
|
||||||
&(*m_handlers), &CoreHandlers::receivedMessage,
|
&(*m_handlers), &CoreHandlers::messageReceived,
|
||||||
this, [this](const std::shared_ptr<linphone::ChatMessage> &message) {
|
this, [this](const std::shared_ptr<linphone::ChatMessage> &message) {
|
||||||
const QString &sip_address = ::Utils::linphoneStringToQString(message->getFromAddress()->asStringUriOnly());
|
const QString &sip_address = ::Utils::linphoneStringToQString(message->getFromAddress()->asStringUriOnly());
|
||||||
addOrUpdateSipAddress(sip_address, nullptr, message);
|
addOrUpdateSipAddress(sip_address, nullptr, message);
|
||||||
|
|
@ -104,13 +104,33 @@ void SipAddressesModel::connectToChatModel (ChatModel *chat_model) {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
for (auto &signal : { &ChatModel::messageSent, &ChatModel::messageReceived }) {
|
||||||
|
QObject::connect(
|
||||||
|
chat_model, signal,
|
||||||
|
this, [this](const std::shared_ptr<linphone::ChatMessage> &message) {
|
||||||
|
addOrUpdateSipAddress(
|
||||||
|
::Utils::linphoneStringToQString(message->getToAddress()->asStringUriOnly()), nullptr, message
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
QObject::connect(
|
QObject::connect(
|
||||||
chat_model, &ChatModel::messageSent,
|
chat_model, &ChatModel::messagesCountReset, this, [this, chat_model]() {
|
||||||
this, [this](const std::shared_ptr<linphone::ChatMessage> &message) {
|
const QString &sip_address = chat_model->getSipAddress();
|
||||||
addOrUpdateSipAddress(
|
|
||||||
::Utils::linphoneStringToQString(message->getToAddress()->asStringUriOnly()), nullptr, message
|
auto it = m_sip_addresses.find(sip_address);
|
||||||
);
|
if (it != m_sip_addresses.end()) {
|
||||||
});
|
(*it)["unreadMessagesCount"] = 0;
|
||||||
|
|
||||||
|
int row = m_refs.indexOf(&(*it));
|
||||||
|
Q_ASSERT(row != -1);
|
||||||
|
emit dataChanged(index(row, 0), index(row, 0));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,9 @@
|
||||||
import QtQuick 2.7
|
import QtQuick 2.7
|
||||||
import QtQuick.Layouts 1.3
|
import QtQuick.Layouts 1.3
|
||||||
|
|
||||||
import Common 1.0
|
|
||||||
import Linphone 1.0
|
import Linphone 1.0
|
||||||
import LinphoneUtils 1.0
|
import LinphoneUtils 1.0
|
||||||
import Linphone.Styles 1.0
|
import Linphone.Styles 1.0
|
||||||
import Utils 1.0
|
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
|
|
@ -14,10 +12,11 @@ Rectangle {
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
property alias actions: actionBar.data
|
|
||||||
property alias sipAddressColor: description.sipAddressColor
|
property alias sipAddressColor: description.sipAddressColor
|
||||||
property alias usernameColor: description.usernameColor
|
property alias usernameColor: description.usernameColor
|
||||||
|
|
||||||
|
property bool displayUnreadMessagesCount: false
|
||||||
|
|
||||||
property var entry
|
property var entry
|
||||||
|
|
||||||
property var _contact: entry.contact
|
property var _contact: entry.contact
|
||||||
|
|
@ -33,7 +32,7 @@ Rectangle {
|
||||||
leftMargin: ContactStyle.leftMargin
|
leftMargin: ContactStyle.leftMargin
|
||||||
rightMargin: ContactStyle.rightMargin
|
rightMargin: ContactStyle.rightMargin
|
||||||
}
|
}
|
||||||
spacing: ContactStyle.spacing
|
spacing: 0
|
||||||
|
|
||||||
Avatar {
|
Avatar {
|
||||||
id: avatar
|
id: avatar
|
||||||
|
|
@ -50,14 +49,17 @@ Rectangle {
|
||||||
|
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
Layout.leftMargin: ContactStyle.spacing
|
||||||
|
|
||||||
sipAddress: entry.sipAddress
|
sipAddress: entry.sipAddress
|
||||||
username: avatar.username
|
username: avatar.username
|
||||||
}
|
}
|
||||||
|
|
||||||
ActionBar {
|
MessagesCounter {
|
||||||
id: actionBar
|
Layout.alignment: Qt.AlignTop
|
||||||
|
|
||||||
Layout.preferredHeight: ContactStyle.contentHeight
|
count: entry.unreadMessagesCount || 0
|
||||||
|
visible: displayUnreadMessagesCount && entry.unreadMessagesCount > 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
40
tests/ui/modules/Linphone/Contact/MessagesCounter.qml
Normal file
40
tests/ui/modules/Linphone/Contact/MessagesCounter.qml
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
|
||||||
|
import Common 1.0
|
||||||
|
import Linphone.Styles 1.0
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: messagesCounter
|
||||||
|
|
||||||
|
property int count
|
||||||
|
|
||||||
|
implicitHeight: counterIcon.height + MessagesCounterStyle.verticalMargins * 2
|
||||||
|
implicitWidth: counterIcon.width + MessagesCounterStyle.horizontalMargins * 2
|
||||||
|
|
||||||
|
Icon {
|
||||||
|
id: counterIcon
|
||||||
|
|
||||||
|
anchors.centerIn: parent
|
||||||
|
|
||||||
|
icon: 'chat_count'
|
||||||
|
iconSize: MessagesCounterStyle.iconSize.message
|
||||||
|
|
||||||
|
Icon {
|
||||||
|
anchors.horizontalCenter: parent.right
|
||||||
|
anchors.verticalCenter: parent.bottom
|
||||||
|
|
||||||
|
icon: 'chat_amount'
|
||||||
|
iconSize: MessagesCounterStyle.iconSize.amount
|
||||||
|
|
||||||
|
Text {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
color: MessagesCounterStyle.text.color
|
||||||
|
font.pointSize: MessagesCounterStyle.text.fontSize
|
||||||
|
text: messagesCounter.count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
pragma Singleton
|
||||||
|
import QtQuick 2.7
|
||||||
|
|
||||||
|
import Common 1.0
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
QtObject {
|
||||||
|
property int horizontalMargins: 0
|
||||||
|
property int verticalMargins: 10
|
||||||
|
|
||||||
|
property QtObject iconSize: QtObject {
|
||||||
|
property int amount: 16
|
||||||
|
property int message: 18
|
||||||
|
}
|
||||||
|
|
||||||
|
property QtObject text: QtObject {
|
||||||
|
property color color: Colors.k
|
||||||
|
property int fontSize: 7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -11,6 +11,7 @@ singleton ChatStyle 1.0 ChatStyle.qml
|
||||||
singleton AvatarStyle 1.0 Contact/AvatarStyle.qml
|
singleton AvatarStyle 1.0 Contact/AvatarStyle.qml
|
||||||
singleton ContactDescriptionStyle 1.0 Contact/ContactDescriptionStyle.qml
|
singleton ContactDescriptionStyle 1.0 Contact/ContactDescriptionStyle.qml
|
||||||
singleton ContactStyle 1.0 Contact/ContactStyle.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 NotificationStyle.qml
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,7 @@ ColumnLayout {
|
||||||
? TimelineStyle.contact.backgroundColor.a
|
? TimelineStyle.contact.backgroundColor.a
|
||||||
: TimelineStyle.contact.backgroundColor.b
|
: TimelineStyle.contact.backgroundColor.b
|
||||||
)
|
)
|
||||||
|
displayUnreadMessagesCount: view.currentIndex !== index
|
||||||
entry: $timelineEntry
|
entry: $timelineEntry
|
||||||
sipAddressColor: view.currentIndex === index
|
sipAddressColor: view.currentIndex === index
|
||||||
? TimelineStyle.contact.sipAddress.color.selected
|
? TimelineStyle.contact.sipAddress.color.selected
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue