imdn on each chat message

imdn on chat last message

change message notification ui

press enter to send message
This commit is contained in:
Gaelle Braud 2025-05-12 16:01:00 +02:00
parent c0dbc4b0e5
commit 9b67794752
22 changed files with 427 additions and 248 deletions

View file

@ -69,18 +69,22 @@ ChatCore::ChatCore(const std::shared_ptr<linphone::ChatRoom> &chatRoom) : QObjec
}); });
mChatModel = Utils::makeQObject_ptr<ChatModel>(chatRoom); mChatModel = Utils::makeQObject_ptr<ChatModel>(chatRoom);
mChatModel->setSelf(mChatModel); mChatModel->setSelf(mChatModel);
mLastMessageInHistory = mChatModel->getLastMessageInHistory(); auto lastMessage = chatRoom->getLastMessageInHistory();
mLastMessage = lastMessage ? ChatMessageCore::create(lastMessage) : nullptr;
auto history = chatRoom->getHistory(0, (int)linphone::ChatRoom::HistoryFilter::ChatMessage); auto history = chatRoom->getHistory(0, (int)linphone::ChatRoom::HistoryFilter::ChatMessage);
std::list<std::shared_ptr<linphone::ChatMessage>> linHistory; std::list<std::shared_ptr<linphone::ChatMessage>> lHistory;
for (auto &eventLog : history) { for (auto &eventLog : history) {
if (eventLog->getChatMessage()) linHistory.push_back(eventLog->getChatMessage()); if (eventLog->getChatMessage()) lHistory.push_back(eventLog->getChatMessage());
} }
for (auto &message : linHistory) { for (auto &message : lHistory) {
if (!message) continue; if (!message) continue;
auto chatMessage = ChatMessageCore::create(message); auto chatMessage = ChatMessageCore::create(message);
mChatMessageList.append(chatMessage); mChatMessageList.append(chatMessage);
} }
mIdentifier = Utils::coreStringToAppString(chatRoom->getIdentifier()); mIdentifier = Utils::coreStringToAppString(chatRoom->getIdentifier());
connect(this, &ChatCore::messageListChanged, this, &ChatCore::lUpdateLastMessage);
connect(this, &ChatCore::messagesInserted, this, &ChatCore::lUpdateLastMessage);
connect(this, &ChatCore::messageRemoved, this, &ChatCore::lUpdateLastMessage);
} }
ChatCore::~ChatCore() { ChatCore::~ChatCore() {
@ -123,16 +127,14 @@ void ChatCore::setSelf(QSharedPointer<ChatCore> me) {
[this](const std::shared_ptr<linphone::ChatRoom> &chatRoom, [this](const std::shared_ptr<linphone::ChatRoom> &chatRoom,
const std::shared_ptr<const linphone::EventLog> &eventLog) { const std::shared_ptr<const linphone::EventLog> &eventLog) {
if (mChatModel->getMonitor() != chatRoom) return; if (mChatModel->getMonitor() != chatRoom) return;
emit lUpdateLastMessage();
emit lUpdateUnreadCount();
emit lUpdateLastUpdatedTime();
auto message = eventLog->getChatMessage(); auto message = eventLog->getChatMessage();
qDebug() << "EVENT LOG RECEIVED IN CHATROOM" << mChatModel->getTitle(); qDebug() << "EVENT LOG RECEIVED IN CHATROOM" << mChatModel->getTitle();
if (message) { if (message) {
auto newMessage = ChatMessageCore::create(message); auto newMessage = ChatMessageCore::create(message);
mChatModelConnection->invokeToCore([this, newMessage]() { mChatModelConnection->invokeToCore([this, newMessage]() {
qDebug() << log().arg("append message to chatRoom") << this;
appendMessageToMessageList(newMessage); appendMessageToMessageList(newMessage);
emit lUpdateUnreadCount();
emit lUpdateLastUpdatedTime();
}); });
} }
}); });
@ -140,9 +142,6 @@ void ChatCore::setSelf(QSharedPointer<ChatCore> me) {
&ChatModel::chatMessagesReceived, [this](const std::shared_ptr<linphone::ChatRoom> &chatRoom, &ChatModel::chatMessagesReceived, [this](const std::shared_ptr<linphone::ChatRoom> &chatRoom,
const std::list<std::shared_ptr<linphone::EventLog>> &chatMessages) { const std::list<std::shared_ptr<linphone::EventLog>> &chatMessages) {
if (mChatModel->getMonitor() != chatRoom) return; if (mChatModel->getMonitor() != chatRoom) return;
emit lUpdateLastMessage();
emit lUpdateUnreadCount();
emit lUpdateLastUpdatedTime();
qDebug() << "EVENT LOGS RECEIVED IN CHATROOM" << mChatModel->getTitle(); qDebug() << "EVENT LOGS RECEIVED IN CHATROOM" << mChatModel->getTitle();
QList<QSharedPointer<ChatMessageCore>> list; QList<QSharedPointer<ChatMessageCore>> list;
for (auto &m : chatMessages) { for (auto &m : chatMessages) {
@ -153,8 +152,9 @@ void ChatCore::setSelf(QSharedPointer<ChatCore> me) {
} }
} }
mChatModelConnection->invokeToCore([this, list]() { mChatModelConnection->invokeToCore([this, list]() {
qDebug() << log().arg("append messages to chatRoom") << this;
appendMessagesToMessageList(list); appendMessagesToMessageList(list);
emit lUpdateUnreadCount();
emit lUpdateLastUpdatedTime();
}); });
}); });
@ -167,12 +167,17 @@ void ChatCore::setSelf(QSharedPointer<ChatCore> me) {
}); });
mChatModelConnection->makeConnectToCore(&ChatCore::lUpdateLastMessage, [this]() { mChatModelConnection->makeConnectToCore(&ChatCore::lUpdateLastMessage, [this]() {
mChatModelConnection->invokeToModel([this]() { auto lastMessageModel = mLastMessage ? mLastMessage->getModel() : nullptr;
auto message = mChatModel->getLastMessageInHistory(); mChatModelConnection->invokeToModel([this, lastMessageModel]() {
mChatModelConnection->invokeToCore([this, message]() { setLastMessageInHistory(message); }); auto linphoneMessage = mChatModel->getLastChatMessage();
if (lastMessageModel && lastMessageModel->getMonitor() != linphoneMessage) {
auto chatMessageCore = ChatMessageCore::create(linphoneMessage);
mChatModelConnection->invokeToCore([this, chatMessageCore]() { setLastMessage(chatMessageCore); });
}
}); });
}); });
mChatModelConnection->makeConnectToCore(&ChatCore::lSendTextMessage, [this](QString message) { mChatModelConnection->makeConnectToCore(&ChatCore::lSendTextMessage, [this](QString message) {
if (Utils::isEmptyMessage(message)) return;
mChatModelConnection->invokeToModel([this, message]() { mChatModelConnection->invokeToModel([this, message]() {
auto linMessage = mChatModel->createTextMessageFromText(message); auto linMessage = mChatModel->createTextMessageFromText(message);
linMessage->send(); linMessage->send();
@ -253,14 +258,28 @@ void ChatCore::setAvatarUri(QString avatarUri) {
} }
} }
QString ChatCore::getLastMessageInHistory() const { QString ChatCore::getLastMessageText() const {
return mLastMessageInHistory; return mLastMessage ? mLastMessage->getText() : QString();
} }
void ChatCore::setLastMessageInHistory(QString lastMessageInHistory) { LinphoneEnums::ChatMessageState ChatCore::getLastMessageState() const {
if (mLastMessageInHistory != lastMessageInHistory) { return mLastMessage ? mLastMessage->getMessageState() : LinphoneEnums::ChatMessageState::StateIdle;
mLastMessageInHistory = lastMessageInHistory; }
emit lastMessageInHistoryChanged(lastMessageInHistory);
ChatMessageGui *ChatCore::getLastMessage() const {
return mLastMessage ? new ChatMessageGui(mLastMessage) : nullptr;
}
QSharedPointer<ChatMessageCore> ChatCore::getLastMessageCore() const {
return mLastMessage;
}
void ChatCore::setLastMessage(QSharedPointer<ChatMessageCore> lastMessage) {
if (mLastMessage != lastMessage) {
disconnect(mLastMessage.get());
mLastMessage = lastMessage;
connect(mLastMessage.get(), &ChatMessageCore::messageStateChanged, this, &ChatCore::lastMessageChanged);
emit lastMessageChanged();
} }
} }

View file

@ -21,7 +21,7 @@
#ifndef CHAT_CORE_H_ #ifndef CHAT_CORE_H_
#define CHAT_CORE_H_ #define CHAT_CORE_H_
#include "core/chat/message/ChatMessageCore.hpp" #include "core/chat/message/ChatMessageGui.hpp"
#include "model/chat/ChatModel.hpp" #include "model/chat/ChatModel.hpp"
#include "model/search/MagicSearchModel.hpp" #include "model/search/MagicSearchModel.hpp"
#include "tool/LinphoneEnums.hpp" #include "tool/LinphoneEnums.hpp"
@ -39,8 +39,9 @@ public:
Q_PROPERTY(QString peerAddress READ getPeerAddress WRITE setPeerAddress NOTIFY peerAddressChanged) Q_PROPERTY(QString peerAddress READ getPeerAddress WRITE setPeerAddress NOTIFY peerAddressChanged)
Q_PROPERTY(QString avatarUri READ getAvatarUri WRITE setAvatarUri NOTIFY avatarUriChanged) Q_PROPERTY(QString avatarUri READ getAvatarUri WRITE setAvatarUri NOTIFY avatarUriChanged)
Q_PROPERTY(QDateTime lastUpdatedTime READ getLastUpdatedTime WRITE setLastUpdatedTime NOTIFY lastUpdatedTimeChanged) Q_PROPERTY(QDateTime lastUpdatedTime READ getLastUpdatedTime WRITE setLastUpdatedTime NOTIFY lastUpdatedTimeChanged)
Q_PROPERTY(QString lastMessageInHistory READ getLastMessageInHistory WRITE setLastMessageInHistory NOTIFY Q_PROPERTY(QString lastMessageText READ getLastMessageText NOTIFY lastMessageChanged)
lastMessageInHistoryChanged) Q_PROPERTY(ChatMessageGui *lastMessage READ getLastMessage NOTIFY lastMessageChanged)
Q_PROPERTY(LinphoneEnums::ChatMessageState lastMessageState READ getLastMessageState NOTIFY lastMessageChanged)
Q_PROPERTY(int unreadMessagesCount READ getUnreadMessagesCount WRITE setUnreadMessagesCount NOTIFY Q_PROPERTY(int unreadMessagesCount READ getUnreadMessagesCount WRITE setUnreadMessagesCount NOTIFY
unreadMessagesCountChanged) unreadMessagesCountChanged)
Q_PROPERTY(QString composingName READ getComposingName WRITE setComposingName NOTIFY composingUserChanged) Q_PROPERTY(QString composingName READ getComposingName WRITE setComposingName NOTIFY composingUserChanged)
@ -61,8 +62,13 @@ public:
QString getIdentifier() const; QString getIdentifier() const;
QString getLastMessageInHistory() const; ChatMessageGui *getLastMessage() const;
void setLastMessageInHistory(QString message); QString getLastMessageText() const;
LinphoneEnums::ChatMessageState getLastMessageState() const;
QSharedPointer<ChatMessageCore> getLastMessageCore() const;
void setLastMessage(QSharedPointer<ChatMessageCore> lastMessage);
int getUnreadMessagesCount() const; int getUnreadMessagesCount() const;
void setUnreadMessagesCount(int count); void setUnreadMessagesCount(int count);
@ -89,7 +95,7 @@ public:
signals: signals:
void lastUpdatedTimeChanged(QDateTime time); void lastUpdatedTimeChanged(QDateTime time);
void lastMessageInHistoryChanged(QString time); void lastMessageChanged();
void titleChanged(QString title); void titleChanged(QString title);
void peerAddressChanged(QString address); void peerAddressChanged(QString address);
void unreadMessagesCountChanged(int count); void unreadMessagesCountChanged(int count);
@ -113,7 +119,6 @@ signals:
private: private:
QString id; QString id;
QDateTime mLastUpdatedTime; QDateTime mLastUpdatedTime;
QString mLastMessageInHistory;
QString mPeerAddress; QString mPeerAddress;
QString mTitle; QString mTitle;
QString mIdentifier; QString mIdentifier;
@ -122,6 +127,7 @@ private:
QString mComposingName; QString mComposingName;
QString mComposingAddress; QString mComposingAddress;
std::shared_ptr<ChatModel> mChatModel; std::shared_ptr<ChatModel> mChatModel;
QSharedPointer<ChatMessageCore> mLastMessage;
QList<QSharedPointer<ChatMessageCore>> mChatMessageList; QList<QSharedPointer<ChatMessageCore>> mChatMessageList;
QSharedPointer<SafeConnection<ChatCore, ChatModel>> mChatModelConnection; QSharedPointer<SafeConnection<ChatCore, ChatModel>> mChatModelConnection;

View file

@ -52,6 +52,25 @@ ChatList::~ChatList() {
mModelConnection = nullptr; mModelConnection = nullptr;
} }
void ChatList::connectItem(QSharedPointer<ChatCore> chat) {
connect(chat.get(), &ChatCore::deleted, this, [this, chat] {
remove(chat);
// We cannot use countChanged here because it is called before mList
// really has removed the item, then emit specific signal
emit chatRemoved(chat ? new ChatGui(chat) : nullptr);
});
auto dataChange = [this, chat] {
int i = -1;
get(chat.get(), &i);
if (i != -1) {
auto modelIndex = index(i);
emit dataChanged(modelIndex, modelIndex);
}
};
connect(chat.get(), &ChatCore::unreadMessagesCountChanged, this, dataChange);
connect(chat.get(), &ChatCore::lastUpdatedTimeChanged, this, dataChange);
}
void ChatList::setSelf(QSharedPointer<ChatList> me) { void ChatList::setSelf(QSharedPointer<ChatList> me) {
mModelConnection = SafeConnection<ChatList, CoreModel>::create(me, CoreModel::getInstance()); mModelConnection = SafeConnection<ChatList, CoreModel>::create(me, CoreModel::getInstance());
@ -70,16 +89,12 @@ void ChatList::setSelf(QSharedPointer<ChatList> me) {
for (auto &chat : getSharedList<ChatCore>()) { for (auto &chat : getSharedList<ChatCore>()) {
if (chat) { if (chat) {
disconnect(chat.get(), &ChatCore::deleted, this, nullptr); disconnect(chat.get(), &ChatCore::deleted, this, nullptr);
disconnect(chat.get(), &ChatCore::unreadMessagesCountChanged, this, nullptr);
disconnect(chat.get(), &ChatCore::lastUpdatedTimeChanged, this, nullptr);
} }
} }
for (auto &chat : *chats) { for (auto &chat : *chats) {
connect(chat.get(), &ChatCore::deleted, this, [this, chat] { connectItem(chat);
remove(chat);
// We cannot use countChanged here because it is called before mList
// really has removed the item, then emit specific signal
emit chatRemoved(chat ? new ChatGui(chat) : nullptr);
});
connect(chat.get(), &ChatCore::unreadMessagesCountChanged, this, [this] { emit chatUpdated(); });
} }
mustBeInMainThread(getClassName()); mustBeInMainThread(getClassName());
resetData<ChatCore>(*chats); resetData<ChatCore>(*chats);

View file

@ -39,6 +39,7 @@ public:
ChatList(QObject *parent = Q_NULLPTR); ChatList(QObject *parent = Q_NULLPTR);
~ChatList(); ~ChatList();
void setSelf(QSharedPointer<ChatList> me); void setSelf(QSharedPointer<ChatList> me);
void connectItem(QSharedPointer<ChatCore> chat);
int findChatIndex(ChatGui *chat); int findChatIndex(ChatGui *chat);
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;

View file

@ -45,9 +45,9 @@ void ChatProxy::setSourceModel(QAbstractItemModel *model) {
[this, newChatList] { emit newChatList->filterChanged(getFilterText()); }); [this, newChatList] { emit newChatList->filterChanged(getFilterText()); });
connect(newChatList, &ChatList::chatRemoved, this, &ChatProxy::chatRemoved); connect(newChatList, &ChatList::chatRemoved, this, &ChatProxy::chatRemoved);
// connect(newChatList, &ChatList::chatAdded, this, [this] { invalidate(); }); // connect(newChatList, &ChatList::chatAdded, this, [this] { invalidate(); });
connect(newChatList, &ChatList::chatUpdated, this, [this] { invalidate(); });
} }
auto firstList = new SortFilterList(model, Qt::AscendingOrder); auto firstList = new SortFilterList(model, Qt::AscendingOrder);
firstList->setDynamicSortFilter(true);
setSourceModels(firstList); setSourceModels(firstList);
sort(0); sort(0);
} }

View file

@ -54,6 +54,7 @@ ChatMessageCore::ChatMessageCore(const std::shared_ptr<linphone::ChatMessage> &c
mIsFromChatGroup = chatroom->hasCapability((int)linphone::ChatRoom::Capabilities::Conference) && mIsFromChatGroup = chatroom->hasCapability((int)linphone::ChatRoom::Capabilities::Conference) &&
!chatroom->hasCapability((int)linphone::ChatRoom::Capabilities::OneToOne); !chatroom->hasCapability((int)linphone::ChatRoom::Capabilities::OneToOne);
mIsRead = chatmessage->isRead(); mIsRead = chatmessage->isRead();
mMessageState = LinphoneEnums::fromLinphone(chatmessage->getState());
} }
ChatMessageCore::~ChatMessageCore() { ChatMessageCore::~ChatMessageCore() {
@ -72,6 +73,14 @@ void ChatMessageCore::setSelf(QSharedPointer<ChatMessageCore> me) {
mChatMessageModelConnection->invokeToModel([this] { mChatMessageModel->markAsRead(); }); mChatMessageModelConnection->invokeToModel([this] { mChatMessageModel->markAsRead(); });
}); });
mChatMessageModelConnection->makeConnectToModel(&ChatMessageModel::messageRead, [this]() { setIsRead(true); }); mChatMessageModelConnection->makeConnectToModel(&ChatMessageModel::messageRead, [this]() { setIsRead(true); });
mChatMessageModelConnection->makeConnectToModel(
&ChatMessageModel::msgStateChanged,
[this](const std::shared_ptr<linphone::ChatMessage> &message, linphone::ChatMessage::State state) {
if (mChatMessageModel->getMonitor() != message) return;
auto msgState = LinphoneEnums::fromLinphone(state);
mChatMessageModelConnection->invokeToCore([this, msgState] { setMessageState(msgState); });
});
} }
QDateTime ChatMessageCore::getTimestamp() const { QDateTime ChatMessageCore::getTimestamp() const {
@ -135,6 +144,17 @@ void ChatMessageCore::setIsRead(bool read) {
} }
} }
LinphoneEnums::ChatMessageState ChatMessageCore::getMessageState() const {
return mMessageState;
}
void ChatMessageCore::setMessageState(LinphoneEnums::ChatMessageState state) {
if (mMessageState != state) {
mMessageState = state;
emit messageStateChanged();
}
}
std::shared_ptr<ChatMessageModel> ChatMessageCore::getModel() const { std::shared_ptr<ChatMessageModel> ChatMessageCore::getModel() const {
return mChatMessageModel; return mChatMessageModel;
} }

View file

@ -40,6 +40,8 @@ class ChatMessageCore : public QObject, public AbstractObject {
Q_PROPERTY(QString toAddress READ getToAddress CONSTANT) Q_PROPERTY(QString toAddress READ getToAddress CONSTANT)
Q_PROPERTY(QString peerName READ getPeerName CONSTANT) Q_PROPERTY(QString peerName READ getPeerName CONSTANT)
Q_PROPERTY(QString fromName READ getFromName CONSTANT) Q_PROPERTY(QString fromName READ getFromName CONSTANT)
Q_PROPERTY(LinphoneEnums::ChatMessageState messageState READ getMessageState WRITE setMessageState NOTIFY
messageStateChanged)
Q_PROPERTY(bool isRemoteMessage READ isRemoteMessage CONSTANT) Q_PROPERTY(bool isRemoteMessage READ isRemoteMessage CONSTANT)
Q_PROPERTY(bool isFromChatGroup READ isFromChatGroup CONSTANT) Q_PROPERTY(bool isFromChatGroup READ isFromChatGroup CONSTANT)
Q_PROPERTY(bool isRead READ isRead WRITE setIsRead NOTIFY isReadChanged) Q_PROPERTY(bool isRead READ isRead WRITE setIsRead NOTIFY isReadChanged)
@ -68,6 +70,9 @@ public:
bool isRead() const; bool isRead() const;
void setIsRead(bool read); void setIsRead(bool read);
LinphoneEnums::ChatMessageState getMessageState() const;
void setMessageState(LinphoneEnums::ChatMessageState state);
std::shared_ptr<ChatMessageModel> getModel() const; std::shared_ptr<ChatMessageModel> getModel() const;
signals: signals:
@ -75,6 +80,7 @@ signals:
void textChanged(QString text); void textChanged(QString text);
void isReadChanged(bool read); void isReadChanged(bool read);
void isRemoteMessageChanged(bool isRemote); void isRemoteMessageChanged(bool isRemote);
void messageStateChanged();
void lDelete(); void lDelete();
void deleted(); void deleted();
@ -92,6 +98,8 @@ private:
bool mIsRemoteMessage = false; bool mIsRemoteMessage = false;
bool mIsFromChatGroup = false; bool mIsFromChatGroup = false;
bool mIsRead = false; bool mIsRead = false;
LinphoneEnums::ChatMessageState mMessageState;
std::shared_ptr<ChatMessageModel> mChatMessageModel; std::shared_ptr<ChatMessageModel> mChatMessageModel;
QSharedPointer<SafeConnection<ChatMessageCore, ChatMessageModel>> mChatMessageModelConnection; QSharedPointer<SafeConnection<ChatMessageCore, ChatMessageModel>> mChatMessageModelConnection;
}; };

View file

@ -88,23 +88,8 @@ QString ChatModel::getPeerAddress() const {
return Utils::coreStringToAppString(mMonitor->getPeerAddress()->asStringUriOnly()); return Utils::coreStringToAppString(mMonitor->getPeerAddress()->asStringUriOnly());
} }
QString ChatModel::getLastMessageInHistory(std::list<std::shared_ptr<linphone::Content>> startList) const { std::shared_ptr<linphone::ChatMessage> ChatModel::getLastChatMessage() {
if (startList.empty()) { return mMonitor->getLastMessageInHistory();
auto lastMessage = mMonitor->getLastMessageInHistory();
if (lastMessage) startList = lastMessage->getContents();
}
for (auto &content : startList) {
if (content->isText()) {
return Utils::coreStringToAppString(content->getUtf8Text());
} else if (content->isFile()) {
return Utils::coreStringToAppString(content->getName());
} else if (content->isIcalendar()) {
return QString("Invitation à une réunion");
} else if (content->isMultipart()) {
return getLastMessageInHistory(content->getParts());
}
}
return QString("");
} }
int ChatModel::getUnreadMessagesCount() const { int ChatModel::getUnreadMessagesCount() const {
@ -137,6 +122,10 @@ void ChatModel::compose() {
mMonitor->compose(); mMonitor->compose();
} }
linphone::ChatRoom::State ChatModel::getState() const {
return mMonitor->getState();
}
//---------------------------------------------------------------// //---------------------------------------------------------------//
void ChatModel::onIsComposingReceived(const std::shared_ptr<linphone::ChatRoom> &chatRoom, void ChatModel::onIsComposingReceived(const std::shared_ptr<linphone::ChatRoom> &chatRoom,

View file

@ -40,7 +40,7 @@ public:
QDateTime getLastUpdateTime(); QDateTime getLastUpdateTime();
QString getTitle(); QString getTitle();
QString getPeerAddress() const; QString getPeerAddress() const;
QString getLastMessageInHistory(std::list<std::shared_ptr<linphone::Content>> startList = {}) const; std::shared_ptr<linphone::ChatMessage> getLastChatMessage();
int getUnreadMessagesCount() const; int getUnreadMessagesCount() const;
void markAsRead(); void markAsRead();
std::list<std::shared_ptr<linphone::ChatMessage>> getHistory() const; std::list<std::shared_ptr<linphone::ChatMessage>> getHistory() const;
@ -49,6 +49,7 @@ public:
void deleteChatRoom(); void deleteChatRoom();
std::shared_ptr<linphone::ChatMessage> createTextMessageFromText(QString text); std::shared_ptr<linphone::ChatMessage> createTextMessageFromText(QString text);
void compose(); void compose();
linphone::ChatRoom::State getState() const;
signals: signals:
void historyDeleted(); void historyDeleted();

View file

@ -60,14 +60,6 @@ QDateTime ChatMessageModel::getTimestamp() const {
return QDateTime::fromSecsSinceEpoch(mMonitor->getTime()); return QDateTime::fromSecsSinceEpoch(mMonitor->getTime());
} }
std::shared_ptr<linphone::Buffer>
ChatMessageModel::onFileTransferSend(const std::shared_ptr<linphone::ChatMessage> &message,
const std::shared_ptr<linphone::Content> &content,
size_t offset,
size_t size) {
return nullptr;
}
bool ChatMessageModel::isRead() const { bool ChatMessageModel::isRead() const {
return mMonitor->isRead(); return mMonitor->isRead();
} }
@ -85,3 +77,88 @@ void ChatMessageModel::deleteMessageFromChatRoom() {
emit messageDeleted(); emit messageDeleted();
} }
} }
linphone::ChatMessage::State ChatMessageModel::getState() const {
return mMonitor->getState();
}
void ChatMessageModel::computeDeliveryStatus() {
// Read
for (auto &participant : mMonitor->getParticipantsByImdnState(linphone::ChatMessage::State::Displayed)) {
}
// Received
for (auto &participant : mMonitor->getParticipantsByImdnState(linphone::ChatMessage::State::DeliveredToUser)) {
}
// Sent
for (auto &participant : mMonitor->getParticipantsByImdnState(linphone::ChatMessage::State::Delivered)) {
}
// Error
for (auto &participant : mMonitor->getParticipantsByImdnState(linphone::ChatMessage::State::NotDelivered)) {
}
}
void ChatMessageModel::onMsgStateChanged(const std::shared_ptr<linphone::ChatMessage> &message,
linphone::ChatMessage::State state) {
computeDeliveryStatus();
emit msgStateChanged(message, state);
}
void ChatMessageModel::onNewMessageReaction(const std::shared_ptr<linphone::ChatMessage> &message,
const std::shared_ptr<const linphone::ChatMessageReaction> &reaction) {
emit newMessageReaction(message, reaction);
}
void ChatMessageModel::onReactionRemoved(const std::shared_ptr<linphone::ChatMessage> &message,
const std::shared_ptr<const linphone::Address> &address) {
emit reactionRemoved(message, address);
}
void ChatMessageModel::onFileTransferTerminated(const std::shared_ptr<linphone::ChatMessage> &message,
const std::shared_ptr<linphone::Content> &content) {
emit fileTransferTerminated(message, content);
}
void ChatMessageModel::onFileTransferRecv(const std::shared_ptr<linphone::ChatMessage> &message,
const std::shared_ptr<linphone::Content> &content,
const std::shared_ptr<const linphone::Buffer> &buffer) {
emit fileTransferRecv(message, content, buffer);
}
std::shared_ptr<linphone::Buffer>
ChatMessageModel::onFileTransferSend(const std::shared_ptr<linphone::ChatMessage> &message,
const std::shared_ptr<linphone::Content> &content,
size_t offset,
size_t size) {
emit fileTransferSend(message, content, offset, size);
return nullptr;
}
void ChatMessageModel::onFileTransferSendChunk(const std::shared_ptr<linphone::ChatMessage> &message,
const std::shared_ptr<linphone::Content> &content,
size_t offset,
size_t size,
const std::shared_ptr<linphone::Buffer> &buffer) {
emit fileTransferSendChunk(message, content, offset, size, buffer);
}
void ChatMessageModel::onFileTransferProgressIndication(const std::shared_ptr<linphone::ChatMessage> &message,
const std::shared_ptr<linphone::Content> &content,
size_t offset,
size_t total) {
emit fileTransferProgressIndication(message, content, offset, total);
}
void ChatMessageModel::onParticipantImdnStateChanged(
const std::shared_ptr<linphone::ChatMessage> &message,
const std::shared_ptr<const linphone::ParticipantImdnState> &state) {
computeDeliveryStatus();
emit participantImdnStateChanged(message, state);
}
void ChatMessageModel::onEphemeralMessageTimerStarted(const std::shared_ptr<linphone::ChatMessage> &message) {
emit ephemeralMessageTimerStarted(message);
}
void ChatMessageModel::onEphemeralMessageDeleted(const std::shared_ptr<linphone::ChatMessage> &message) {
emit ephemeralMessageDeleted(message);
}

View file

@ -49,16 +49,74 @@ public:
void deleteMessageFromChatRoom(); void deleteMessageFromChatRoom();
void computeDeliveryStatus();
linphone::ChatMessage::State getState() const;
signals: signals:
void messageDeleted(); void messageDeleted();
void messageRead(); void messageRead();
void msgStateChanged(const std::shared_ptr<linphone::ChatMessage> &message, linphone::ChatMessage::State state);
void newMessageReaction(const std::shared_ptr<linphone::ChatMessage> &message,
const std::shared_ptr<const linphone::ChatMessageReaction> &reaction);
void reactionRemoved(const std::shared_ptr<linphone::ChatMessage> &message,
const std::shared_ptr<const linphone::Address> &address);
void fileTransferTerminated(const std::shared_ptr<linphone::ChatMessage> &message,
const std::shared_ptr<linphone::Content> &content);
void fileTransferRecv(const std::shared_ptr<linphone::ChatMessage> &message,
const std::shared_ptr<linphone::Content> &content,
const std::shared_ptr<const linphone::Buffer> &buffer);
void fileTransferSend(const std::shared_ptr<linphone::ChatMessage> &message,
const std::shared_ptr<linphone::Content> &content,
size_t offset,
size_t size);
void fileTransferSendChunk(const std::shared_ptr<linphone::ChatMessage> &message,
const std::shared_ptr<linphone::Content> &content,
size_t offset,
size_t size,
const std::shared_ptr<linphone::Buffer> &buffer);
void fileTransferProgressIndication(const std::shared_ptr<linphone::ChatMessage> &message,
const std::shared_ptr<linphone::Content> &content,
size_t offset,
size_t total);
void participantImdnStateChanged(const std::shared_ptr<linphone::ChatMessage> &message,
const std::shared_ptr<const linphone::ParticipantImdnState> &state);
void ephemeralMessageTimerStarted(const std::shared_ptr<linphone::ChatMessage> &message);
void ephemeralMessageDeleted(const std::shared_ptr<linphone::ChatMessage> &message);
private: private:
linphone::ChatMessage::State mMessageState;
DECLARE_ABSTRACT_OBJECT DECLARE_ABSTRACT_OBJECT
virtual std::shared_ptr<linphone::Buffer> onFileTransferSend(const std::shared_ptr<linphone::ChatMessage> &message,
const std::shared_ptr<linphone::Content> &content, void onMsgStateChanged(const std::shared_ptr<linphone::ChatMessage> &message, linphone::ChatMessage::State state);
size_t offset, void onNewMessageReaction(const std::shared_ptr<linphone::ChatMessage> &message,
size_t size) override; const std::shared_ptr<const linphone::ChatMessageReaction> &reaction);
void onReactionRemoved(const std::shared_ptr<linphone::ChatMessage> &message,
const std::shared_ptr<const linphone::Address> &address);
void onFileTransferTerminated(const std::shared_ptr<linphone::ChatMessage> &message,
const std::shared_ptr<linphone::Content> &content);
void onFileTransferRecv(const std::shared_ptr<linphone::ChatMessage> &message,
const std::shared_ptr<linphone::Content> &content,
const std::shared_ptr<const linphone::Buffer> &buffer);
std::shared_ptr<linphone::Buffer> onFileTransferSend(const std::shared_ptr<linphone::ChatMessage> &message,
const std::shared_ptr<linphone::Content> &content,
size_t offset,
size_t size);
void onFileTransferSendChunk(const std::shared_ptr<linphone::ChatMessage> &message,
const std::shared_ptr<linphone::Content> &content,
size_t offset,
size_t size,
const std::shared_ptr<linphone::Buffer> &buffer);
void onFileTransferProgressIndication(const std::shared_ptr<linphone::ChatMessage> &message,
const std::shared_ptr<linphone::Content> &content,
size_t offset,
size_t total);
void onParticipantImdnStateChanged(const std::shared_ptr<linphone::ChatMessage> &message,
const std::shared_ptr<const linphone::ParticipantImdnState> &state);
void onEphemeralMessageTimerStarted(const std::shared_ptr<linphone::ChatMessage> &message);
void onEphemeralMessageDeleted(const std::shared_ptr<linphone::ChatMessage> &message);
}; };
#endif #endif

View file

@ -1582,6 +1582,10 @@ VariantObject *Utils::getChatForAddress(QString address) {
return data; return data;
} }
bool Utils::isEmptyMessage(QString message) {
return message.trimmed().isEmpty();
}
// CLI // CLI
void Utils::runCommandLine(const QString command) { void Utils::runCommandLine(const QString command) {

View file

@ -148,6 +148,7 @@ public:
Q_INVOKABLE static VariantObject *getCurrentCallChat(CallGui *call); Q_INVOKABLE static VariantObject *getCurrentCallChat(CallGui *call);
Q_INVOKABLE static VariantObject *getChatForAddress(QString address); Q_INVOKABLE static VariantObject *getChatForAddress(QString address);
Q_INVOKABLE static bool isEmptyMessage(QString message);
// QDir findDirectoryByName(QString startPath, QString name); // QDir findDirectoryByName(QString startPath, QString name);
static QString getApplicationProduct(); static QString getApplicationProduct();

View file

@ -185,7 +185,7 @@ ListView {
Text { Text {
Layout.fillWidth: true Layout.fillWidth: true
maximumLineCount: 1 maximumLineCount: 1
text: modelData.core.lastMessageInHistory text: modelData.core.lastMessageText
color: DefaultStyle.main2_400 color: DefaultStyle.main2_400
font { font {
pixelSize: Typography.p1.pixelSize pixelSize: Typography.p1.pixelSize
@ -194,25 +194,45 @@ ListView {
} }
} }
ColumnLayout { ColumnLayout {
Text { Layout.alignment: Qt.AlignRight
color: DefaultStyle.main2_500main RowLayout {
text: UtilsCpp.formatDate(modelData.core.lastUpdatedTime, true, false) Item{Layout.fillWidth: true}
font { Text {
pixelSize: Typography.p3.pixelSize color: DefaultStyle.main2_500main
weight: Typography.p3.weight text: UtilsCpp.formatDate(modelData.core.lastUpdatedTime, true, false)
capitalization: Font.Capitalize font {
pixelSize: Typography.p3.pixelSize
weight: Typography.p3.weight
capitalization: Font.Capitalize
}
} }
} }
RowLayout { RowLayout {
spacing: Math.round(10 * DefaultStyle.dp)
Item {Layout.fillWidth: true} Item {Layout.fillWidth: true}
//sourdine, éphémère
UnreadNotification { UnreadNotification {
id: unreadCount id: unreadCount
unread: modelData.core.unreadMessagesCount unread: modelData.core.unreadMessagesCount
} }
//sourdine, éphémère, IMDN EffectImage {
visible: modelData?.core.lastMessage && modelData?.core.lastMessageState !== LinphoneEnums.ChatMessageState.StateIdle
&& !modelData.core.lastMessage.core.isRemoteMessage
Layout.preferredWidth: visible ? 14 * DefaultStyle.dp : 0
Layout.preferredHeight: 14 * DefaultStyle.dp
colorizationColor: DefaultStyle.main1_500_main
imageSource: modelData.core.lastMessageState === LinphoneEnums.ChatMessageState.StateDelivered
? AppIcons.envelope
: modelData.core.lastMessageState === LinphoneEnums.ChatMessageState.StateDeliveredToUser
? AppIcons.check
: modelData.core.lastMessageState === LinphoneEnums.ChatMessageState.StateNotDelivered
? AppIcons.warningCircle
: modelData.core.lastMessageState === LinphoneEnums.ChatMessageState.StateDisplayed
? AppIcons.checks
: ""
}
} }
} }
PopupButton { PopupButton {
@ -251,6 +271,7 @@ ListView {
hoverEnabled: true hoverEnabled: true
anchors.fill: parent anchors.fill: parent
focus: true focus: true
acceptedButtons: Qt.RightButton | Qt.LeftButton
onContainsMouseChanged: { onContainsMouseChanged: {
if (containsMouse) if (containsMouse)
mainItem.lastMouseContainsIndex = index mainItem.lastMouseContainsIndex = index
@ -265,8 +286,12 @@ ListView {
visible: mainItem.lastMouseContainsIndex === index || mainItem.currentIndex === index visible: mainItem.lastMouseContainsIndex === index || mainItem.currentIndex === index
} }
onPressed: { onPressed: {
mainItem.currentIndex = model.index if (pressedButtons & Qt.RightButton) {
mainItem.forceActiveFocus() chatroomPopup.open()
} else {
mainItem.currentIndex = model.index
mainItem.forceActiveFocus()
}
} }
} }
} }

View file

@ -19,6 +19,8 @@ Control.Control {
property string fromAddress: chatMessage? chatMessage.core.fromAddress : "" property string fromAddress: chatMessage? chatMessage.core.fromAddress : ""
property bool isRemoteMessage: chatMessage? chatMessage.core.isRemoteMessage : false property bool isRemoteMessage: chatMessage? chatMessage.core.isRemoteMessage : false
property bool isFromChatGroup: chatMessage? chatMessage.core.isFromChatGroup : false property bool isFromChatGroup: chatMessage? chatMessage.core.isFromChatGroup : false
property var msgState: chatMessage ? chatMessage.core.messageState : LinphoneEnums.ChatMessageState.StateIdle
onMsgStateChanged: console.log("message state", msgState, chatMessage.core.text)
hoverEnabled: true hoverEnabled: true
signal messageDeletionRequested() signal messageDeletionRequested()
@ -62,9 +64,9 @@ Control.Control {
Layout.preferredWidth: Math.min(implicitWidth, mainItem.maxWidth - avatar.implicitWidth) Layout.preferredWidth: Math.min(implicitWidth, mainItem.maxWidth - avatar.implicitWidth)
spacing: Math.round(2 * DefaultStyle.dp) spacing: Math.round(2 * DefaultStyle.dp)
topPadding: Math.round(12 * DefaultStyle.dp) topPadding: Math.round(12 * DefaultStyle.dp)
bottomPadding: Math.round(12 * DefaultStyle.dp) bottomPadding: Math.round(6 * DefaultStyle.dp)
leftPadding: Math.round(18 * DefaultStyle.dp) leftPadding: Math.round(12 * DefaultStyle.dp)
rightPadding: Math.round(18 * DefaultStyle.dp) rightPadding: Math.round(12 * DefaultStyle.dp)
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
@ -110,19 +112,38 @@ Control.Control {
visible: modelData.core.text != undefined visible: modelData.core.text != undefined
text: modelData.core.text text: modelData.core.text
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true
horizontalAlignment: modelData.core.isRemoteMessage ? Text.AlignLeft : Text.AlignRight
color: DefaultStyle.main2_700 color: DefaultStyle.main2_700
font { font {
pixelSize: Typography.p1.pixelSize pixelSize: Typography.p1.pixelSize
weight: Typography.p1.weight weight: Typography.p1.weight
} }
} }
Text { RowLayout {
Layout.alignment: Qt.AlignRight Layout.alignment: Qt.AlignRight
text: UtilsCpp.formatDate(modelData.core.timestamp, true, false) Text {
color: DefaultStyle.main2_500main text: UtilsCpp.formatDate(modelData.core.timestamp, true, false)
font { color: DefaultStyle.main2_500main
pixelSize: Typography.p3.pixelSize font {
weight: Typography.p3.weight pixelSize: Typography.p3.pixelSize
weight: Typography.p3.weight
}
}
EffectImage {
visible: !mainItem.isRemoteMessage
Layout.preferredWidth: visible ? 14 * DefaultStyle.dp : 0
Layout.preferredHeight: 14 * DefaultStyle.dp
colorizationColor: DefaultStyle.main1_500_main
imageSource: mainItem.msgState === LinphoneEnums.ChatMessageState.StateDelivered
? AppIcons.envelope
: mainItem.msgState === LinphoneEnums.ChatMessageState.StateDeliveredToUser
? AppIcons.check
: mainItem.msgState === LinphoneEnums.ChatMessageState.StateNotDelivered
? AppIcons.warningCircle
: mainItem.msgState === LinphoneEnums.ChatMessageState.StateDisplayed
? AppIcons.checks
: ""
} }
} }
} }

View file

@ -20,6 +20,13 @@ ListView {
var chatMessage = chatMessageProxy.getChatMessageAtIndex(index) var chatMessage = chatMessageProxy.getChatMessageAtIndex(index)
if (chatMessage && !chatMessage.core.isRead) chatMessage.core.lMarkAsRead() if (chatMessage && !chatMessage.core.isRead) chatMessage.core.lMarkAsRead()
} }
onCountChanged: if (atYEnd) {
var index = chatMessageProxy.findFirstUnreadIndex()
mainItem.positionViewAtIndex(index, ListView.End)
var chatMessage = chatMessageProxy.getChatMessageAtIndex(index)
if (chatMessage && !chatMessage.core.isRead) chatMessage.core.lMarkAsRead()
}
Button { Button {
visible: !mainItem.atYEnd visible: !mainItem.atYEnd

View file

@ -5,10 +5,8 @@ import QtQuick.Controls.Basic
import QtQuick.Layouts import QtQuick.Layouts
import Qt.labs.platform import Qt.labs.platform
// =============================================================================
Window { Window {
id: mainItem id: mainItem
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -17,8 +15,6 @@ Window {
property bool requestActivate: false property bool requestActivate: false
//property int flags: Qt.SplashScreen //property int flags: Qt.SplashScreen
default property alias _content: content.data default property alias _content: content.data
property bool _isOpen: false property bool _isOpen: false
signal isOpened() signal isOpened()
@ -89,100 +85,4 @@ Window {
} }
] ]
*/ */
} }
/*
Item {
id: wrapper
objectName: '__internalWrapper'
// ---------------------------------------------------------------------------
property alias popupX: window.x
property alias popupY: window.y
property bool requestActivate: false
property int flags: Qt.SplashScreen
readonly property alias popupWidth: window.width
readonly property alias popupHeight: window.height
default property alias _content: content.data
property bool _isOpen: false
signal isOpened()
signal isClosed()
signal dataChanged()
on_ContentChanged: dataChanged(_content)
// ---------------------------------------------------------------------------
function open () {
_isOpen = true;
isOpened();
}
function close () {
_isOpen = false
isClosed()
}
// ---------------------------------------------------------------------------
// No size, no position.
height: 0
width: 0
visible:true
Window {
id: window
objectName: '__internalWindow'
property bool isFrameLess : false;
property bool showAsTool : false
// Don't use Popup for flags : it could lead to error in geometry. On Mac, Using Tool ensure to have the Window on Top and fullscreen independant
flags: Qt.BypassWindowManagerHint | (showAsTool?Qt.Tool:Qt.WindowStaysOnTopHint) | Qt.Window | Qt.FramelessWindowHint;
onXChanged: console.log(x)
opacity: 1.0
height: _content[0] != null ? _content[0].height : 0
width: _content[0] != null ? _content[0].width : 0
visible:true
Item {
id: content
anchors.fill:parent
property var $parent: wrapper
}
}
// ---------------------------------------------------------------------------
states: State {
name: 'opening'
when: _isOpen
PropertyChanges {
opacity: 1.0
target: window
}
}
transitions: [
Transition {
from: ''
to: 'opening'
ScriptAction {
script: {
if (wrapper.requestActivate) {
window.requestActivate()
}
}
}
},
Transition {
from: '*'
to: ''
ScriptAction {
script: window.close()
}
}
]
}
*/

View file

@ -8,7 +8,7 @@ import 'qrc:/qt/qml/Linphone/view/Style/buttonStyle.js' as ButtonStyle
Notification { Notification {
id: mainItem id: mainItem
radius: Math.round(20 * DefaultStyle.dp) radius: Math.round(10 * DefaultStyle.dp)
backgroundColor: DefaultStyle.grey_600 backgroundColor: DefaultStyle.grey_600
backgroundOpacity: 0.8 backgroundOpacity: 0.8
overriddenWidth: Math.round(400 * DefaultStyle.dp) overriddenWidth: Math.round(400 * DefaultStyle.dp)

View file

@ -9,7 +9,7 @@ import 'qrc:/qt/qml/Linphone/view/Style/buttonStyle.js' as ButtonStyle
Notification { Notification {
id: mainItem id: mainItem
radius: Math.round(20 * DefaultStyle.dp) radius: Math.round(10 * DefaultStyle.dp)
backgroundColor: DefaultStyle.grey_600 backgroundColor: DefaultStyle.grey_600
backgroundOpacity: 0.8 backgroundOpacity: 0.8
overriddenWidth: Math.round(400 * DefaultStyle.dp) overriddenWidth: Math.round(400 * DefaultStyle.dp)
@ -26,14 +26,15 @@ Notification {
width: parent.width width: parent.width
leftPadding: Math.round(18 * DefaultStyle.dp) leftPadding: Math.round(18 * DefaultStyle.dp)
rightPadding: Math.round(18 * DefaultStyle.dp) rightPadding: Math.round(18 * DefaultStyle.dp)
topPadding: Math.round(9 * DefaultStyle.dp) topPadding: Math.round(32 * DefaultStyle.dp)
bottomPadding: Math.round(18 * DefaultStyle.dp) bottomPadding: Math.round(18 * DefaultStyle.dp)
background: Item{} background: Item {
contentItem: ColumnLayout { anchors.fill: parent
spacing: Math.round(9 * DefaultStyle.dp)
RowLayout { RowLayout {
anchors.top: parent.top
anchors.topMargin: Math.round(9 * DefaultStyle.dp)
anchors.horizontalCenter: parent.horizontalCenter
spacing: Math.round(4 * DefaultStyle.dp) spacing: Math.round(4 * DefaultStyle.dp)
Layout.alignment: Qt.AlignHCenter
Image { Image {
Layout.preferredWidth: Math.round(12 * DefaultStyle.dp) Layout.preferredWidth: Math.round(12 * DefaultStyle.dp)
Layout.preferredHeight: Math.round(12 * DefaultStyle.dp) Layout.preferredHeight: Math.round(12 * DefaultStyle.dp)
@ -49,65 +50,75 @@ Notification {
} }
} }
} }
ColumnLayout { Button {
spacing: Math.round(14 * DefaultStyle.dp) anchors.top: parent.top
Layout.alignment: Qt.AlignHCenter anchors.right: parent.right
Layout.fillWidth: true anchors.topMargin: Math.round(9 * DefaultStyle.dp)
RowLayout { anchors.rightMargin: Math.round(12 * DefaultStyle.dp)
spacing: Math.round(10 * DefaultStyle.dp) padding: 0
Avatar { z: mousearea.z + 1
Layout.preferredWidth: Math.round(45 * DefaultStyle.dp) background: Item{anchors.fill: parent}
Layout.preferredHeight: Math.round(45 * DefaultStyle.dp) icon.source: AppIcons.closeX
Layout.alignment: Qt.AlignHCenter width: Math.round(14 * DefaultStyle.dp)
property var contactObj: UtilsCpp.findFriendByAddress(mainItem.remoteAddress) height: Math.round(14 * DefaultStyle.dp)
contact: contactObj?.value || null icon.width: Math.round(14 * DefaultStyle.dp)
displayNameVal: contact ? "" : mainItem.avatarUri icon.height: Math.round(14 * DefaultStyle.dp)
} contentImageColor: DefaultStyle.grey_0
ColumnLayout { onPressed: {
spacing: 0 mainItem._close()
Text {
text: mainItem.chatRoomName
color: DefaultStyle.main2_200
Layout.fillWidth: true
maximumLineCount: 1
font {
pixelSize: Typography.h3.pixelSize
weight: Typography.h3.weight
capitalization: Font.Capitalize
}
}
Text {
text: mainItem.remoteAddress
color: DefaultStyle.main2_100
Layout.fillWidth: true
maximumLineCount: 1
font {
pixelSize: Typography.p1.pixelSize
weight: Typography.p1.weight
}
}
}
Item{Layout.fillWidth: true}
} }
Rectangle { }
Layout.fillWidth: true MouseArea {
id: mousearea
anchors.fill: parent
onClicked: {
console.log("notif clicked, open chat")
}
}
}
contentItem: ColumnLayout {
spacing: Math.round(9 * DefaultStyle.dp)
RowLayout {
spacing: Math.round(14 * DefaultStyle.dp)
Avatar {
Layout.preferredWidth: Math.round(60 * DefaultStyle.dp)
Layout.preferredHeight: Math.round(60 * DefaultStyle.dp) Layout.preferredHeight: Math.round(60 * DefaultStyle.dp)
color: DefaultStyle.main2_400 // Layout.alignment: Qt.AlignHCenter
radius: Math.round(5 * DefaultStyle.dp) property var contactObj: UtilsCpp.findFriendByAddress(mainItem.remoteAddress)
contact: contactObj?.value || null
displayNameVal: contact ? "" : mainItem.avatarUri
}
ColumnLayout {
spacing: 0
Text {
text: mainItem.chatRoomName
color: DefaultStyle.grey_100
Layout.fillWidth: true
maximumLineCount: 1
font {
pixelSize: Typography.h4.pixelSize
weight: Typography.h4.weight
capitalization: Font.Capitalize
}
}
Text {
text: mainItem.remoteAddress
color: DefaultStyle.main2_100
Layout.fillWidth: true
maximumLineCount: 1
font {
pixelSize: Typography.p4.pixelSize
weight: Typography.p4.weight
}
}
Text { Text {
anchors.fill: parent
anchors.leftMargin: 8 * DefaultStyle.dp
anchors.rightMargin: 8 * DefaultStyle.dp
anchors.topMargin: 8 * DefaultStyle.dp
anchors.bottomMargin: 8 * DefaultStyle.dp
verticalAlignment: Text.AlignVCenter
text: mainItem.message text: mainItem.message
Layout.fillWidth: true
maximumLineCount: 2 maximumLineCount: 2
color: DefaultStyle.grey_1000 color: DefaultStyle.grey_300
font { font {
pixelSize: Typography.p1s.pixelSize pixelSize: Typography.p1s.pixelSize
weight: Typography.p1s.weight weight: Typography.p1s.weight
italic: true
} }
} }
} }

View file

@ -153,6 +153,10 @@ RowLayout {
anchors.fill: parent anchors.fill: parent
radius: Math.round(35 * DefaultStyle.dp) radius: Math.round(35 * DefaultStyle.dp)
color: DefaultStyle.grey_0 color: DefaultStyle.grey_0
MouseArea {
anchors.fill: parent
onPressed: sendingTextArea.forceActiveFocus()
}
} }
contentItem: RowLayout { contentItem: RowLayout {
Flickable { Flickable {
@ -204,6 +208,16 @@ RowLayout {
if (previousText === "" && text !== "") { if (previousText === "" && text !== "") {
mainItem.chat.core.lCompose() mainItem.chat.core.lCompose()
} }
previousText = text
}
Keys.onPressed: (event) => {
event.accepted = false
if (UtilsCpp.isEmptyMessage(sendingTextArea.text)) return
if (!(event.modifiers & Qt.ControlModifier) && (event.key == Qt.Key_Return || event.key == Qt.Key_Enter)) {
mainItem.chat.core.lSendTextMessage(sendingTextArea.text)
sendingTextArea.clear()
event.accepted = true
}
} }
} }
} }

View file

@ -131,7 +131,7 @@ AbstractMainPage {
anchors.fill: parent anchors.fill: parent
anchors.rightMargin: Math.round(39 * DefaultStyle.dp) anchors.rightMargin: Math.round(39 * DefaultStyle.dp)
Text { Text {
visible: chatListView.count === 0 visible: chatListView.count === 0 && chatListView.loading === false
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Layout.topMargin: Math.round(137 * DefaultStyle.dp) Layout.topMargin: Math.round(137 * DefaultStyle.dp)
//: "Aucun résultat" //: "Aucun résultat"

View file

@ -30,7 +30,9 @@ QtObject {
property string profile: "image://internal/user-circle.svg" property string profile: "image://internal/user-circle.svg"
property string manageProfile: "image://internal/user-circle-gear.svg" property string manageProfile: "image://internal/user-circle-gear.svg"
property string verif_page_image: "image://internal/verif_page_image.svg" property string verif_page_image: "image://internal/verif_page_image.svg"
property string envelope: "image://internal/envelope-simple.svg"
property string check: "image://internal/check.svg" property string check: "image://internal/check.svg"
property string checks: "image://internal/checks.svg"
property string dialer: "image://internal/numpad.svg" property string dialer: "image://internal/numpad.svg"
property string chiffrement: "image://internal/chiffrement.svg" property string chiffrement: "image://internal/chiffrement.svg"
property string interoperable: "image://internal/interoperable.svg" property string interoperable: "image://internal/interoperable.svg"