mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-01-17 03:18:07 +00:00
open chat room from call/conf
navigate to chat from contact/history/magic search select chat when joining from contact/history/magic search message notification filter chat rooms
This commit is contained in:
parent
8516a3febf
commit
b79b324027
43 changed files with 692 additions and 154 deletions
|
|
@ -43,17 +43,17 @@ ChatCore::ChatCore(const std::shared_ptr<linphone::ChatRoom> &chatRoom) : QObjec
|
|||
mLastUpdatedTime = QDateTime::fromSecsSinceEpoch(chatRoom->getLastUpdateTime());
|
||||
if (chatRoom->hasCapability((int)linphone::ChatRoom::Capabilities::Basic)) {
|
||||
mTitle = ToolModel::getDisplayName(chatRoom->getPeerAddress()->clone());
|
||||
mAvatarUri = Utils::coreStringToAppString(chatRoom->getPeerAddress()->asStringUriOnly());
|
||||
mAvatarUri = ToolModel::getDisplayName(chatRoom->getPeerAddress()->clone());
|
||||
auto peerAddress = chatRoom->getPeerAddress();
|
||||
mPeerAddress = Utils::coreStringToAppString(peerAddress->asStringUriOnly());
|
||||
} else {
|
||||
if (chatRoom->hasCapability((int)linphone::ChatRoom::Capabilities::OneToOne)) {
|
||||
auto peer = chatRoom->getParticipants().front();
|
||||
if (peer) mTitle = ToolModel::getDisplayName(peer->getAddress()->clone());
|
||||
mAvatarUri = Utils::coreStringToAppString(peer->getAddress()->asStringUriOnly());
|
||||
auto participants = chatRoom->getParticipants();
|
||||
auto peer = participants.front();
|
||||
if (peer) mTitle = ToolModel::getDisplayName(peer->getAddress()->clone());
|
||||
mAvatarUri = ToolModel::getDisplayName(peer->getAddress()->clone());
|
||||
if (participants.size() == 1) {
|
||||
auto peerAddress = participants.front()->getAddress();
|
||||
auto peerAddress = peer->getAddress();
|
||||
if (peerAddress) mPeerAddress = Utils::coreStringToAppString(peerAddress->asStringUriOnly());
|
||||
}
|
||||
} else if (chatRoom->hasCapability((int)linphone::ChatRoom::Capabilities::Conference)) {
|
||||
|
|
@ -75,6 +75,7 @@ ChatCore::ChatCore(const std::shared_ptr<linphone::ChatRoom> &chatRoom) : QObjec
|
|||
auto chatMessage = ChatMessageCore::create(message);
|
||||
mChatMessageList.append(chatMessage);
|
||||
}
|
||||
mIdentifier = Utils::coreStringToAppString(chatRoom->getIdentifier());
|
||||
}
|
||||
|
||||
ChatCore::~ChatCore() {
|
||||
|
|
@ -121,6 +122,10 @@ void ChatCore::setTitle(QString title) {
|
|||
}
|
||||
}
|
||||
|
||||
QString ChatCore::getIdentifier() const {
|
||||
return mIdentifier;
|
||||
}
|
||||
|
||||
QString ChatCore::getPeerAddress() const {
|
||||
return mPeerAddress;
|
||||
}
|
||||
|
|
@ -193,3 +198,7 @@ void ChatCore::removeMessagesFromMessageList(QList<QSharedPointer<ChatMessageCor
|
|||
}
|
||||
if (nbRemoved > 0) emit messageListChanged();
|
||||
}
|
||||
|
||||
std::shared_ptr<ChatModel> ChatCore::getModel() const {
|
||||
return mChatModel;
|
||||
}
|
||||
|
|
@ -35,6 +35,7 @@ class ChatCore : public QObject, public AbstractObject {
|
|||
|
||||
public:
|
||||
Q_PROPERTY(QString title READ getTitle WRITE setTitle NOTIFY titleChanged)
|
||||
Q_PROPERTY(QString identifier READ getIdentifier CONSTANT)
|
||||
Q_PROPERTY(QString peerAddress READ getPeerAddress WRITE setPeerAddress NOTIFY peerAddressChanged)
|
||||
Q_PROPERTY(QString avatarUri READ getAvatarUri WRITE setAvatarUri NOTIFY avatarUriChanged)
|
||||
Q_PROPERTY(QDateTime lastUpdatedTime READ getLastUpdatedTime WRITE setLastUpdatedTime NOTIFY lastUpdatedTimeChanged)
|
||||
|
|
@ -56,6 +57,8 @@ public:
|
|||
QString getTitle() const;
|
||||
void setTitle(QString title);
|
||||
|
||||
QString getIdentifier() const;
|
||||
|
||||
QString getLastMessageInHistory() const;
|
||||
void setLastMessageInHistory(QString message);
|
||||
|
||||
|
|
@ -73,6 +76,8 @@ public:
|
|||
QString getAvatarUri() const;
|
||||
void setAvatarUri(QString avatarUri);
|
||||
|
||||
std::shared_ptr<ChatModel> getModel() const;
|
||||
|
||||
signals:
|
||||
void lastUpdatedTimeChanged(QDateTime time);
|
||||
void lastMessageInHistoryChanged(QString time);
|
||||
|
|
@ -88,6 +93,7 @@ private:
|
|||
QString mLastMessageInHistory;
|
||||
QString mPeerAddress;
|
||||
QString mTitle;
|
||||
QString mIdentifier;
|
||||
QString mAvatarUri;
|
||||
int mUnreadMessagesCount;
|
||||
std::shared_ptr<ChatModel> mChatModel;
|
||||
|
|
|
|||
|
|
@ -61,8 +61,7 @@ void ChatList::setSelf(QSharedPointer<ChatList> me) {
|
|||
// Avoid copy to lambdas
|
||||
QList<QSharedPointer<ChatCore>> *chats = new QList<QSharedPointer<ChatCore>>();
|
||||
auto currentAccount = CoreModel::getInstance()->getCore()->getDefaultAccount();
|
||||
// auto linphoneChatRooms = currentAccount->filterChatRooms(Utils::appStringToCoreString(mFilter));
|
||||
auto linphoneChatRooms = currentAccount->getChatRooms();
|
||||
auto linphoneChatRooms = currentAccount->filterChatRooms(Utils::appStringToCoreString(mFilter));
|
||||
for (auto it : linphoneChatRooms) {
|
||||
auto model = createChatCore(it);
|
||||
chats->push_back(model);
|
||||
|
|
@ -75,25 +74,29 @@ void ChatList::setSelf(QSharedPointer<ChatList> me) {
|
|||
});
|
||||
});
|
||||
|
||||
mModelConnection->makeConnectToModel(&CoreModel::chatRoomStateChanged,
|
||||
[this](const std::shared_ptr<linphone::Core> &core,
|
||||
const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
||||
linphone::ChatRoom::State state) {
|
||||
// check account, filtre, puis ajout si c'est bon
|
||||
bool toCreate = false;
|
||||
if (toCreate) {
|
||||
auto model = createChatCore(chatRoom);
|
||||
mModelConnection->invokeToCore([this, model]() {
|
||||
// We set the current here and not on firstChatStarted event
|
||||
// because we don't want to add unicity check while keeping the
|
||||
// same model between list and current chat.
|
||||
add(model);
|
||||
});
|
||||
}
|
||||
});
|
||||
mModelConnection->makeConnectToModel(&CoreModel::defaultAccountChanged, [this] (std::shared_ptr<linphone::Core> core, std::shared_ptr<linphone::Account> account) {
|
||||
lUpdate();
|
||||
});
|
||||
mModelConnection->makeConnectToModel(
|
||||
&CoreModel::chatRoomStateChanged,
|
||||
[this](const std::shared_ptr<linphone::Core> &core, const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
||||
linphone::ChatRoom::State state) {
|
||||
// check account, filtre, puis ajout si c'est bon
|
||||
if (chatRoom->getAccount() == core->getDefaultAccount()) {
|
||||
if (state == linphone::ChatRoom::State::Created) {
|
||||
auto list = getSharedList<ChatCore>();
|
||||
auto found =
|
||||
std::find_if(list.begin(), list.end(), [chatRoom](const QSharedPointer<ChatCore> &item) {
|
||||
return (item && item->getModel()->getMonitor() == chatRoom);
|
||||
});
|
||||
if (found != list.end()) {
|
||||
qDebug() << "chat room created, add it to the list";
|
||||
auto model = createChatCore(chatRoom);
|
||||
mModelConnection->invokeToCore([this, model]() { add(model); });
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
mModelConnection->makeConnectToModel(
|
||||
&CoreModel::defaultAccountChanged,
|
||||
[this](std::shared_ptr<linphone::Core> core, std::shared_ptr<linphone::Account> account) { lUpdate(); });
|
||||
|
||||
connect(this, &ChatList::filterChanged, [this](QString filter) {
|
||||
mFilter = filter;
|
||||
|
|
@ -102,6 +105,16 @@ void ChatList::setSelf(QSharedPointer<ChatList> me) {
|
|||
lUpdate();
|
||||
}
|
||||
|
||||
int ChatList::findChatIndex(ChatGui *chatGui) {
|
||||
if (!chatGui) return -1;
|
||||
auto core = chatGui->mCore;
|
||||
auto chatList = getSharedList<ChatCore>();
|
||||
auto it = std::find_if(chatList.begin(), chatList.end(), [core](const QSharedPointer<ChatCore> item) {
|
||||
return item->getIdentifier() == core->getIdentifier();
|
||||
});
|
||||
return it == chatList.end() ? -1 : std::distance(chatList.begin(), it);
|
||||
}
|
||||
|
||||
QVariant ChatList::data(const QModelIndex &index, int role) const {
|
||||
int row = index.row();
|
||||
if (!index.isValid() || row < 0 || row >= mList.count()) return QVariant();
|
||||
|
|
|
|||
|
|
@ -38,9 +38,11 @@ public:
|
|||
QSharedPointer<ChatCore> createChatCore(const std::shared_ptr<linphone::ChatRoom> &chatroom);
|
||||
ChatList(QObject *parent = Q_NULLPTR);
|
||||
~ChatList();
|
||||
|
||||
void setSelf(QSharedPointer<ChatList> me);
|
||||
|
||||
int findChatIndex(ChatGui *chat);
|
||||
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
signals:
|
||||
void lUpdate();
|
||||
void filterChanged(QString filter);
|
||||
|
|
|
|||
|
|
@ -40,15 +40,30 @@ void ChatProxy::setSourceModel(QAbstractItemModel *model) {
|
|||
}
|
||||
auto newChatList = dynamic_cast<ChatList *>(model);
|
||||
if (newChatList) {
|
||||
// connect(this, &ChatProxy::filterTextChanged, newChatList, &ChatList::filterChanged);
|
||||
connect(this, &ChatProxy::filterTextChanged, newChatList,
|
||||
[this, newChatList] { emit newChatList->filterChanged(getFilterText()); });
|
||||
}
|
||||
setSourceModels(new SortFilterList(model));
|
||||
sort(0);
|
||||
}
|
||||
|
||||
int ChatProxy::findChatIndex(ChatGui *chatGui) {
|
||||
auto chatList = getListModel<ChatList>();
|
||||
if (chatList) {
|
||||
auto listIndex = chatList->findChatIndex(chatGui);
|
||||
if (listIndex != -1) {
|
||||
listIndex =
|
||||
dynamic_cast<SortFilterList *>(sourceModel())->mapFromSource(chatList->index(listIndex, 0)).row();
|
||||
if (mMaxDisplayItems <= listIndex) setMaxDisplayItems(listIndex + mDisplayItemsStep);
|
||||
return listIndex;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool ChatProxy::SortFilterList::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const {
|
||||
// auto l = getItemAtSource<ChatList, ChatCore>(sourceRow);
|
||||
// return l != nullptr;
|
||||
// auto l = getItemAtSource<ChatList, ChatCore>(sourceRow);
|
||||
// return l != nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ public:
|
|||
|
||||
void setSourceModel(QAbstractItemModel *sourceModel) override;
|
||||
|
||||
Q_INVOKABLE int findChatIndex(ChatGui *chatGui);
|
||||
|
||||
protected:
|
||||
QSharedPointer<ChatList> mList;
|
||||
DECLARE_ABSTRACT_OBJECT
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "ChatMessageCore.hpp"
|
||||
#include "core/App.hpp"
|
||||
#include "model/tool/ToolModel.hpp"
|
||||
|
||||
DEFINE_ABSTRACT_OBJECT(ChatMessageCore)
|
||||
|
||||
|
|
@ -31,7 +32,7 @@ QSharedPointer<ChatMessageCore> ChatMessageCore::create(const std::shared_ptr<li
|
|||
}
|
||||
|
||||
ChatMessageCore::ChatMessageCore(const std::shared_ptr<linphone::ChatMessage> &chatmessage) {
|
||||
lDebug() << "[ChatMessageCore] new" << this;
|
||||
// lDebug() << "[ChatMessageCore] new" << this;
|
||||
mustBeInLinphoneThread(getClassName());
|
||||
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::CppOwnership);
|
||||
mChatMessageModel = Utils::makeQObject_ptr<ChatMessageModel>(chatmessage);
|
||||
|
|
@ -41,6 +42,8 @@ ChatMessageCore::ChatMessageCore(const std::shared_ptr<linphone::ChatMessage> &c
|
|||
auto from = chatmessage->getFromAddress();
|
||||
auto to = chatmessage->getLocalAddress();
|
||||
mIsRemoteMessage = !from->weakEqual(to);
|
||||
mPeerAddress = Utils::coreStringToAppString(chatmessage->getPeerAddress()->asStringUriOnly());
|
||||
mPeerName = ToolModel::getDisplayName(chatmessage->getPeerAddress()->clone());
|
||||
}
|
||||
|
||||
ChatMessageCore::~ChatMessageCore() {
|
||||
|
|
@ -72,6 +75,14 @@ void ChatMessageCore::setText(QString text) {
|
|||
}
|
||||
}
|
||||
|
||||
QString ChatMessageCore::getPeerAddress() const {
|
||||
return mPeerAddress;
|
||||
}
|
||||
|
||||
QString ChatMessageCore::getPeerName() const {
|
||||
return mPeerName;
|
||||
}
|
||||
|
||||
bool ChatMessageCore::isRemoteMessage() const {
|
||||
return mIsRemoteMessage;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ class ChatMessageCore : public QObject, public AbstractObject {
|
|||
Q_OBJECT
|
||||
Q_PROPERTY(QDateTime timestamp READ getTimestamp WRITE setTimestamp NOTIFY timestampChanged)
|
||||
Q_PROPERTY(QString text READ getText WRITE setText NOTIFY textChanged)
|
||||
Q_PROPERTY(QString peerAddress READ getPeerAddress CONSTANT)
|
||||
Q_PROPERTY(QString peerName READ getPeerName CONSTANT)
|
||||
Q_PROPERTY(bool isRemoteMessage READ isRemoteMessage WRITE setIsRemoteMessage NOTIFY isRemoteMessageChanged)
|
||||
|
||||
public:
|
||||
|
|
@ -47,6 +49,9 @@ public:
|
|||
QString getText() const;
|
||||
void setText(QString text);
|
||||
|
||||
QString getPeerAddress() const;
|
||||
QString getPeerName() const;
|
||||
|
||||
bool isRemoteMessage() const;
|
||||
void setIsRemoteMessage(bool isRemote);
|
||||
|
||||
|
|
@ -58,6 +63,8 @@ signals:
|
|||
private:
|
||||
DECLARE_ABSTRACT_OBJECT
|
||||
QString mText;
|
||||
QString mPeerAddress;
|
||||
QString mPeerName;
|
||||
QDateTime mTimestamp;
|
||||
bool mIsRemoteMessage = false;
|
||||
std::shared_ptr<ChatMessageModel> mChatMessageModel;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include "core/App.hpp"
|
||||
#include "core/call/CallGui.hpp"
|
||||
#include "core/chat/ChatCore.hpp"
|
||||
#include "model/tool/ToolModel.hpp"
|
||||
#include "tool/LinphoneEnums.hpp"
|
||||
#include "tool/providers/AvatarProvider.hpp"
|
||||
|
|
@ -85,9 +86,9 @@ void setProperty(QObject &object, const char *property, const T &value) {
|
|||
// =============================================================================
|
||||
|
||||
const QHash<int, Notifier::Notification> Notifier::Notifications = {
|
||||
//{Notifier::ReceivedMessage, {Notifier::ReceivedMessage, "NotificationReceivedMessage.qml", 10}},
|
||||
{Notifier::ReceivedMessage, {Notifier::ReceivedMessage, "NotificationReceivedMessage.qml", 10}},
|
||||
//{Notifier::ReceivedFileMessage, {Notifier::ReceivedFileMessage, "NotificationReceivedFileMessage.qml", 10}},
|
||||
{Notifier::ReceivedCall, {Notifier::ReceivedCall, "NotificationReceivedCall.qml", 30}},
|
||||
{Notifier::ReceivedCall, {Notifier::ReceivedCall, "NotificationReceivedCall.qml", 30}}
|
||||
//{Notifier::NewVersionAvailable, {Notifier::NewVersionAvailable, "NotificationNewVersionAvailable.qml", 30}},
|
||||
//{Notifier::SnapshotWasTaken, {Notifier::SnapshotWasTaken, "NotificationSnapshotWasTaken.qml", 10}},
|
||||
//{Notifier::RecordingCompleted, {Notifier::RecordingCompleted, "NotificationRecordingCompleted.qml", 10}}
|
||||
|
|
@ -127,7 +128,7 @@ Notifier::~Notifier() {
|
|||
|
||||
bool Notifier::createNotification(Notifier::NotificationType type, QVariantMap data) {
|
||||
mMutex->lock();
|
||||
Q_ASSERT(mInstancesNumber <= MaxNotificationsNumber);
|
||||
// Q_ASSERT(mInstancesNumber <= MaxNotificationsNumber);
|
||||
if (mInstancesNumber == MaxNotificationsNumber) { // Check existing instances.
|
||||
qWarning() << QStringLiteral("Unable to create another notification.");
|
||||
mMutex->unlock();
|
||||
|
|
@ -305,43 +306,68 @@ void Notifier::notifyReceivedCall(const shared_ptr<linphone::Call> &call) {
|
|||
});
|
||||
}
|
||||
|
||||
/*
|
||||
void Notifier::notifyReceivedMessages(const list<shared_ptr<linphone::ChatMessage>> &messages) {
|
||||
QVariantMap map;
|
||||
QString txt;
|
||||
if (messages.size() > 0) {
|
||||
shared_ptr<linphone::ChatMessage> message = messages.front();
|
||||
void Notifier::notifyReceivedMessages(const std::shared_ptr<linphone::ChatRoom> &room,
|
||||
const list<shared_ptr<linphone::ChatMessage>> &messages) {
|
||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||
|
||||
if (messages.size() == 1) {
|
||||
auto fileContent = message->getFileTransferInformation();
|
||||
if (!fileContent) {
|
||||
foreach (auto content, message->getContents()) {
|
||||
if (content->isText()) txt += content->getUtf8Text().c_str();
|
||||
}
|
||||
} else if (fileContent->isVoiceRecording())
|
||||
//: 'Voice message received!' : message to warn the user in a notofication for voice messages.
|
||||
txt = tr("new_voice_message");
|
||||
else txt = tr("new_file_message");
|
||||
if (txt.isEmpty() && message->hasConferenceInvitationContent())
|
||||
//: 'Conference invitation received!' : Notification about receiving an invitation to a conference.
|
||||
txt = tr("new_conference_invitation");
|
||||
} else
|
||||
//: 'New messages received!' Notification that warn the user of new messages.
|
||||
txt = tr("new_chat_room_messages");
|
||||
map["message"] = txt;
|
||||
shared_ptr<linphone::ChatRoom> chatRoom(message->getChatRoom());
|
||||
map["timelineModel"].setValue(
|
||||
CoreManager::getInstance()->getTimelineListModel()->getTimeline(chatRoom, true).get());
|
||||
if (messages.size() == 1) { // Display only sender on mono message.
|
||||
map["remoteAddress"] = Utils::coreStringToAppString(message->getFromAddress()->asStringUriOnly());
|
||||
map["fullremoteAddress"] = Utils::coreStringToAppString(message->getFromAddress()->asString());
|
||||
}
|
||||
map["localAddress"] = Utils::coreStringToAppString(message->getToAddress()->asStringUriOnly());
|
||||
map["fullLocalAddress"] = Utils::coreStringToAppString(message->getToAddress()->asString());
|
||||
map["window"].setValue(App::getInstance()->getMainWindow());
|
||||
CREATE_NOTIFICATION(Notifier::ReceivedMessage, map)
|
||||
}
|
||||
QString txt;
|
||||
QString remoteAddress;
|
||||
|
||||
if (messages.size() > 0) {
|
||||
shared_ptr<linphone::ChatMessage> message = messages.front();
|
||||
|
||||
auto receiverAccount = ToolModel::findAccount(message->getToAddress());
|
||||
if (receiverAccount) {
|
||||
auto senderAccount = ToolModel::findAccount(message->getFromAddress());
|
||||
if (senderAccount) {
|
||||
return;
|
||||
}
|
||||
auto accountModel = Utils::makeQObject_ptr<AccountModel>(receiverAccount);
|
||||
accountModel->setSelf(accountModel);
|
||||
if (!accountModel->getNotificationsAllowed()) {
|
||||
qInfo() << "Notifications have been disabled for this account - not creating a notification for "
|
||||
"incoming message";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (messages.size() == 1) { // Display only sender on mono message.
|
||||
auto remoteAddr = message->getFromAddress()->clone();
|
||||
remoteAddr->clean();
|
||||
remoteAddress = Utils::coreStringToAppString(remoteAddr->asStringUriOnly());
|
||||
auto fileContent = message->getFileTransferInformation();
|
||||
if (!fileContent) {
|
||||
foreach (auto content, message->getContents()) {
|
||||
if (content->isText()) txt += content->getUtf8Text().c_str();
|
||||
}
|
||||
} else if (fileContent->isVoiceRecording())
|
||||
//: 'Voice message received!' : message to warn the user in a notofication for voice messages.
|
||||
txt = tr("new_voice_message");
|
||||
else txt = tr("new_file_message");
|
||||
if (txt.isEmpty() && message->hasConferenceInvitationContent())
|
||||
//: 'Conference invitation received!' : Notification about receiving an invitation to a conference.
|
||||
txt = tr("new_conference_invitation");
|
||||
} else {
|
||||
//: 'New messages received!' Notification that warn the user of new messages.
|
||||
txt = tr("new_chat_room_messages");
|
||||
}
|
||||
|
||||
auto chatCore = ChatCore::create(room);
|
||||
|
||||
App::postCoreAsync([this, txt, chatCore, remoteAddress]() {
|
||||
mustBeInMainThread(getClassName());
|
||||
QVariantMap map;
|
||||
map["message"] = txt;
|
||||
qDebug() << "create notif from address" << remoteAddress;
|
||||
map["remoteAddress"] = remoteAddress;
|
||||
map["chatRoomName"] = chatCore->getTitle();
|
||||
map["chatRoomAddress"] = chatCore->getPeerAddress();
|
||||
map["avatarUri"] = chatCore->getAvatarUri();
|
||||
CREATE_NOTIFICATION(Notifier::ReceivedMessage, map)
|
||||
});
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
||||
void Notifier::notifyReceivedReactions(
|
||||
const QList<QPair<std::shared_ptr<linphone::ChatMessage>, std::shared_ptr<const linphone::ChatMessageReaction>>>
|
||||
|
|
|
|||
|
|
@ -41,9 +41,9 @@ public:
|
|||
~Notifier();
|
||||
|
||||
enum NotificationType {
|
||||
// ReceivedMessage,
|
||||
ReceivedMessage,
|
||||
// ReceivedFileMessage,
|
||||
ReceivedCall,
|
||||
ReceivedCall
|
||||
// NewVersionAvailable,
|
||||
// SnapshotWasTaken,
|
||||
// RecordingCompleted
|
||||
|
|
@ -52,8 +52,9 @@ public:
|
|||
// void notifyReceivedCall(Call *call);
|
||||
void notifyReceivedCall(const std::shared_ptr<linphone::Call> &call); // Call from Linphone
|
||||
|
||||
void notifyReceivedMessages(const std::shared_ptr<linphone::ChatRoom> &room,
|
||||
const std::list<std::shared_ptr<linphone::ChatMessage>> &messages);
|
||||
/*
|
||||
void notifyReceivedMessages(const std::list<std::shared_ptr<linphone::ChatMessage>> &messages);
|
||||
void notifyReceivedReactions(
|
||||
const QList<QPair<std::shared_ptr<linphone::ChatMessage>, std::shared_ptr<const
|
||||
linphone::ChatMessageReaction>>> &reactions); void notifyReceivedFileMessage(const
|
||||
|
|
|
|||
|
|
@ -110,11 +110,13 @@ int MagicSearchProxy::loadUntil(const QString &address) {
|
|||
auto magicSearchList = getListModel<MagicSearchList>();
|
||||
if (magicSearchList) {
|
||||
auto listIndex = magicSearchList->findFriendIndexByAddress(address);
|
||||
if (listIndex == -1) return -1;
|
||||
listIndex =
|
||||
dynamic_cast<SortFilterList *>(sourceModel())->mapFromSource(magicSearchList->index(listIndex, 0)).row();
|
||||
if (mMaxDisplayItems <= listIndex) setMaxDisplayItems(listIndex + mDisplayItemsStep);
|
||||
return listIndex;
|
||||
if (listIndex != -1) {
|
||||
listIndex = dynamic_cast<SortFilterList *>(sourceModel())
|
||||
->mapFromSource(magicSearchList->index(listIndex, 0))
|
||||
.row();
|
||||
if (mMaxDisplayItems <= listIndex) setMaxDisplayItems(listIndex + mDisplayItemsStep);
|
||||
return listIndex;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -233,6 +233,10 @@ bool CallModel::getZrtpCaseMismatch() const {
|
|||
return mMonitor->getZrtpCacheMismatchFlag();
|
||||
}
|
||||
|
||||
std::shared_ptr<linphone::Conference> CallModel::getConference() const {
|
||||
return mMonitor->getConference();
|
||||
}
|
||||
|
||||
void CallModel::setConference(const std::shared_ptr<linphone::Conference> &conference) {
|
||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||
if (mConference != conference) {
|
||||
|
|
@ -411,7 +415,7 @@ void CallModel::onStateChanged(const std::shared_ptr<linphone::Call> &call,
|
|||
emit localVideoEnabledChanged(videoDirection == linphone::MediaDirection::SendOnly ||
|
||||
videoDirection == linphone::MediaDirection::SendRecv);
|
||||
emit remoteVideoEnabledChanged(remoteVideoDirection == linphone::MediaDirection::SendOnly ||
|
||||
remoteVideoDirection == linphone::MediaDirection::SendRecv);
|
||||
remoteVideoDirection == linphone::MediaDirection::SendRecv);
|
||||
updateConferenceVideoLayout();
|
||||
} else if (state == linphone::Call::State::End || state == linphone::Call::State::Error) {
|
||||
mDurationTimer.stop();
|
||||
|
|
|
|||
|
|
@ -72,6 +72,8 @@ public:
|
|||
QStringList getRemoteAtuhenticationTokens() const;
|
||||
bool getZrtpCaseMismatch() const;
|
||||
|
||||
std::shared_ptr<linphone::Conference> getConference() const;
|
||||
|
||||
LinphoneEnums::ConferenceLayout getConferenceVideoLayout() const;
|
||||
void changeConferenceVideoLayout(LinphoneEnums::ConferenceLayout layout); // Make a call request
|
||||
void updateConferenceVideoLayout(); // Called from call state changed ater the new layout has been set.
|
||||
|
|
|
|||
|
|
@ -54,6 +54,10 @@ std::list<std::shared_ptr<linphone::ChatMessage>> ChatModel::getHistory() const
|
|||
return res;
|
||||
}
|
||||
|
||||
QString ChatModel::getIdentifier() const {
|
||||
return Utils::coreStringToAppString(mMonitor->getIdentifier());
|
||||
}
|
||||
|
||||
QString ChatModel::getTitle() {
|
||||
if (mMonitor->hasCapability((int)linphone::ChatRoom::Capabilities::Basic)) {
|
||||
return ToolModel::getDisplayName(mMonitor->getPeerAddress()->clone());
|
||||
|
|
@ -65,6 +69,7 @@ QString ChatModel::getTitle() {
|
|||
return Utils::coreStringToAppString(mMonitor->getSubject());
|
||||
}
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString ChatModel::getPeerAddress() const {
|
||||
|
|
@ -101,15 +106,14 @@ void ChatModel::onIsComposingReceived(const std::shared_ptr<linphone::ChatRoom>
|
|||
emit isComposingReceived(chatRoom, remoteAddress, isComposing);
|
||||
}
|
||||
|
||||
// Do not use this api, only manipulate EventLogs
|
||||
void ChatModel::onMessageReceived(const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
||||
const std::shared_ptr<linphone::ChatMessage> &message) {
|
||||
// emit messageReceived(chatRoom, message);
|
||||
emit messageReceived(chatRoom, message);
|
||||
}
|
||||
|
||||
void ChatModel::onMessagesReceived(const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
||||
const std::list<std::shared_ptr<linphone::ChatMessage>> &chatMessages) {
|
||||
// emit messagesReceived(chatRoom, chatMessages);
|
||||
emit messagesReceived(chatRoom, chatMessages);
|
||||
}
|
||||
|
||||
void ChatModel::onNewEvent(const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
||||
|
|
@ -258,5 +262,5 @@ void ChatModel::onChatRoomRead(const std::shared_ptr<linphone::ChatRoom> &chatRo
|
|||
void ChatModel::onNewMessageReaction(const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
||||
const std::shared_ptr<linphone::ChatMessage> &message,
|
||||
const std::shared_ptr<const linphone::ChatMessageReaction> &reaction) {
|
||||
emit onNewMessageReaction(chatRoom, message, reaction);
|
||||
// emit onNewMessageReaction(chatRoom, message, reaction);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ public:
|
|||
QString getLastMessageInHistory(std::list<std::shared_ptr<linphone::Content>> startList = {}) const;
|
||||
int getUnreadMessagesCount() const;
|
||||
std::list<std::shared_ptr<linphone::ChatMessage>> getHistory() const;
|
||||
QString getIdentifier() const;
|
||||
|
||||
private:
|
||||
DECLARE_ABSTRACT_OBJECT
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ DEFINE_ABSTRACT_OBJECT(ChatMessageModel)
|
|||
|
||||
ChatMessageModel::ChatMessageModel(const std::shared_ptr<linphone::ChatMessage> &chatMessage, QObject *parent)
|
||||
: ::Listener<linphone::ChatMessage, linphone::ChatMessageListener>(chatMessage, parent) {
|
||||
lDebug() << "[ChatMessageModel] new" << this << " / SDKModel=" << chatMessage.get();
|
||||
// lDebug() << "[ChatMessageModel] new" << this << " / SDKModel=" << chatMessage.get();
|
||||
mustBeInLinphoneThread(getClassName());
|
||||
}
|
||||
|
||||
|
|
@ -44,6 +44,10 @@ QString ChatMessageModel::getText() const {
|
|||
return ToolModel::getMessageFromContent(mMonitor->getContents());
|
||||
}
|
||||
|
||||
QString ChatMessageModel::getPeerAddress() const {
|
||||
return Utils::coreStringToAppString(mMonitor->getPeerAddress()->asStringUriOnly());
|
||||
}
|
||||
|
||||
QDateTime ChatMessageModel::getTimestamp() const {
|
||||
return QDateTime::fromSecsSinceEpoch(mMonitor->getTime());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@ public:
|
|||
QString getText() const;
|
||||
QDateTime getTimestamp() const;
|
||||
|
||||
QString getPeerAddress() const;
|
||||
|
||||
private:
|
||||
DECLARE_ABSTRACT_OBJECT
|
||||
virtual std::shared_ptr<linphone::Buffer> onFileTransferSend(const std::shared_ptr<linphone::ChatMessage> &message,
|
||||
|
|
|
|||
|
|
@ -76,6 +76,10 @@ int ConferenceModel::getParticipantDeviceCount() const {
|
|||
return mMonitor->getParticipantDeviceList().size();
|
||||
}
|
||||
|
||||
std::shared_ptr<linphone::ChatRoom> ConferenceModel::getChatRoom() const {
|
||||
return mMonitor->getChatRoom();
|
||||
}
|
||||
|
||||
void ConferenceModel::setMicrophoneMuted(bool isMuted) {
|
||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||
mMonitor->setMicrophoneMuted(isMuted);
|
||||
|
|
@ -171,7 +175,8 @@ bool ConferenceModel::isScreenSharingEnabled() const {
|
|||
void ConferenceModel::onActiveSpeakerParticipantDevice(
|
||||
const std::shared_ptr<linphone::Conference> &conference,
|
||||
const std::shared_ptr<const linphone::ParticipantDevice> &participantDevice) {
|
||||
lDebug() << "onActiveSpeakerParticipantDevice: " << (participantDevice ? participantDevice->getAddress()->asString().c_str() : "NULL");
|
||||
lDebug() << "onActiveSpeakerParticipantDevice: "
|
||||
<< (participantDevice ? participantDevice->getAddress()->asString().c_str() : "NULL");
|
||||
|
||||
emit activeSpeakerParticipantDevice(conference, conference->getActiveSpeakerParticipantDevice());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,8 @@ public:
|
|||
void removeParticipant(const std::shared_ptr<linphone::Address> &address);
|
||||
void addParticipant(const std::shared_ptr<linphone::Address> &address);
|
||||
|
||||
std::shared_ptr<linphone::ChatRoom> getChatRoom() const;
|
||||
|
||||
int getParticipantDeviceCount() const;
|
||||
|
||||
void onIsScreenSharingEnabledChanged();
|
||||
|
|
|
|||
|
|
@ -122,9 +122,8 @@ void CoreModel::start() {
|
|||
linphoneSearch->setLimitedSearch(true);
|
||||
mMagicSearch = Utils::makeQObject_ptr<MagicSearchModel>(linphoneSearch);
|
||||
mMagicSearch->setSelf(mMagicSearch);
|
||||
connect(mMagicSearch.get(), &MagicSearchModel::searchResultsReceived, this, [this] {
|
||||
emit magicSearchResultReceived(mMagicSearch->mLastSearch);
|
||||
});
|
||||
connect(mMagicSearch.get(), &MagicSearchModel::searchResultsReceived, this,
|
||||
[this] { emit magicSearchResultReceived(mMagicSearch->mLastSearch); });
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -352,10 +351,11 @@ void CoreModel::migrate() {
|
|||
config->setInt(SettingsModel::UiSection, Constants::RcVersionName, Constants::RcVersionCurrent);
|
||||
}
|
||||
|
||||
void CoreModel::searchInMagicSearch(QString filter, int sourceFlags,
|
||||
LinphoneEnums::MagicSearchAggregation aggregation,
|
||||
int maxResults) {
|
||||
mMagicSearch->search(filter, sourceFlags, aggregation, maxResults);
|
||||
void CoreModel::searchInMagicSearch(QString filter,
|
||||
int sourceFlags,
|
||||
LinphoneEnums::MagicSearchAggregation aggregation,
|
||||
int maxResults) {
|
||||
mMagicSearch->search(filter, sourceFlags, aggregation, maxResults);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------------
|
||||
|
|
@ -503,12 +503,16 @@ void CoreModel::onMessageReceived(const std::shared_ptr<linphone::Core> &core,
|
|||
const std::shared_ptr<linphone::ChatRoom> &room,
|
||||
const std::shared_ptr<linphone::ChatMessage> &message) {
|
||||
emit unreadNotificationsChanged();
|
||||
std::list<std::shared_ptr<linphone::ChatMessage>> messages;
|
||||
messages.push_back(message);
|
||||
App::getInstance()->getNotifier()->notifyReceivedMessages(room, messages);
|
||||
emit messageReceived(core, room, message);
|
||||
}
|
||||
void CoreModel::onMessagesReceived(const std::shared_ptr<linphone::Core> &core,
|
||||
const std::shared_ptr<linphone::ChatRoom> &room,
|
||||
const std::list<std::shared_ptr<linphone::ChatMessage>> &messages) {
|
||||
emit unreadNotificationsChanged();
|
||||
App::getInstance()->getNotifier()->notifyReceivedMessages(room, messages);
|
||||
emit messagesReceived(core, room, messages);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@
|
|||
#include "model/cli/CliModel.hpp"
|
||||
#include "model/listener/Listener.hpp"
|
||||
#include "model/logger/LoggerModel.hpp"
|
||||
#include "tool/AbstractObject.hpp"
|
||||
#include "model/search/MagicSearchModel.hpp"
|
||||
#include "tool/AbstractObject.hpp"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
|
|
@ -61,9 +61,9 @@ public:
|
|||
void migrate();
|
||||
|
||||
void searchInMagicSearch(QString filter,
|
||||
int sourceFlags,
|
||||
LinphoneEnums::MagicSearchAggregation aggregation,
|
||||
int maxResults);
|
||||
int sourceFlags,
|
||||
LinphoneEnums::MagicSearchAggregation aggregation,
|
||||
int maxResults);
|
||||
|
||||
bool mEnd = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -120,20 +120,18 @@ std::shared_ptr<linphone::Friend> ToolModel::findFriendByAddress(const QString &
|
|||
auto defaultFriendList = CoreModel::getInstance()->getCore()->getDefaultFriendList();
|
||||
if (!defaultFriendList) return nullptr;
|
||||
auto linphoneAddr = ToolModel::interpretUrl(address);
|
||||
if (linphoneAddr)
|
||||
return ToolModel::findFriendByAddress(linphoneAddr);
|
||||
else
|
||||
return nullptr;
|
||||
if (linphoneAddr) return ToolModel::findFriendByAddress(linphoneAddr);
|
||||
else return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<linphone::Friend> ToolModel::findFriendByAddress(std::shared_ptr<linphone::Address> linphoneAddr) {
|
||||
auto friendsManager = FriendsManager::getInstance();
|
||||
QString key = Utils::coreStringToAppString(linphoneAddr->asStringUriOnly());
|
||||
if (friendsManager->isInKnownFriends(key)) {
|
||||
// qDebug() << key << "have been found in known friend, return it";
|
||||
// qDebug() << key << "have been found in known friend, return it";
|
||||
return friendsManager->getKnownFriendAtKey(key);
|
||||
} else if (friendsManager->isInUnknownFriends(key)) {
|
||||
// qDebug() << key << "have been found in unknown friend, return it";
|
||||
} else if (friendsManager->isInUnknownFriends(key)) {
|
||||
// qDebug() << key << "have been found in unknown friend, return it";
|
||||
return friendsManager->getUnknownFriendAtKey(key);
|
||||
}
|
||||
auto f = CoreModel::getInstance()->getCore()->findFriend(linphoneAddr);
|
||||
|
|
@ -141,20 +139,21 @@ std::shared_ptr<linphone::Friend> ToolModel::findFriendByAddress(std::shared_ptr
|
|||
if (friendsManager->isInUnknownFriends(key)) {
|
||||
friendsManager->removeUnknownFriend(key);
|
||||
}
|
||||
// qDebug() << "found friend, add to known map";
|
||||
// qDebug() << "found friend, add to known map";
|
||||
friendsManager->appendKnownFriend(linphoneAddr, f);
|
||||
}
|
||||
if (!f) {
|
||||
if (friendsManager->isInOtherAddresses(key)) {
|
||||
// qDebug() << "A magic search has already be done for address" << key << "and nothing was found, return";
|
||||
// qDebug() << "A magic search has already be done for address" << key << "and nothing was found,
|
||||
// return";
|
||||
return nullptr;
|
||||
}
|
||||
friendsManager->appendOtherAddress(key);
|
||||
// qDebug() << "Couldn't find friend" << linphoneAddr->asStringUriOnly() << "in core, use magic search";
|
||||
// qDebug() << "Couldn't find friend" << linphoneAddr->asStringUriOnly() << "in core, use magic search";
|
||||
CoreModel::getInstance()->searchInMagicSearch(Utils::coreStringToAppString(linphoneAddr->asStringUriOnly()),
|
||||
(int)linphone::MagicSearch::Source::LdapServers
|
||||
| (int)linphone::MagicSearch::Source::RemoteCardDAV
|
||||
, LinphoneEnums::MagicSearchAggregation::Friend, 50);
|
||||
(int)linphone::MagicSearch::Source::LdapServers |
|
||||
(int)linphone::MagicSearch::Source::RemoteCardDAV,
|
||||
LinphoneEnums::MagicSearchAggregation::Friend, 50);
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
|
@ -384,7 +383,6 @@ bool ToolModel::friendIsInFriendList(const std::shared_ptr<linphone::FriendList>
|
|||
return (it != friends.end());
|
||||
}
|
||||
|
||||
|
||||
QString ToolModel::getMessageFromContent(std::list<std::shared_ptr<linphone::Content>> contents) {
|
||||
for (auto &content : contents) {
|
||||
if (content->isText()) {
|
||||
|
|
@ -467,3 +465,118 @@ QString ToolModel::computeUserAgent(const std::shared_ptr<linphone::Config> &con
|
|||
.arg(qVersion())
|
||||
.remove("'");
|
||||
}
|
||||
|
||||
std::shared_ptr<linphone::ConferenceParams>
|
||||
ToolModel::getChatRoomParams(std::shared_ptr<linphone::Call> call, std::shared_ptr<linphone::Address> remoteAddress) {
|
||||
auto core = call ? call->getCore() : CoreModel::getInstance()->getCore();
|
||||
auto localAddress = call ? call->getCallLog()->getLocalAddress() : nullptr;
|
||||
if (!remoteAddress && call) remoteAddress = call->getRemoteAddress()->clone();
|
||||
auto account = findAccount(localAddress);
|
||||
if (!account) account = core->getDefaultAccount();
|
||||
if (!account) qWarning() << "failed to get account, return";
|
||||
if (!account) return nullptr;
|
||||
|
||||
auto params = core->createConferenceParams(call ? call->getConference() : nullptr);
|
||||
params->enableChat(true);
|
||||
params->enableGroup(false);
|
||||
//: Dummy subject
|
||||
params->setSubject(Utils::appStringToCoreString(QObject::tr("chat_dummy_subject")));
|
||||
params->setAccount(account);
|
||||
|
||||
auto chatParams = params->getChatParams();
|
||||
if (!chatParams) {
|
||||
qWarning() << "failed to get chat params from conference params, return";
|
||||
return nullptr;
|
||||
}
|
||||
chatParams->setEphemeralLifetime(0);
|
||||
auto accountParams = account->getParams();
|
||||
auto sameDomain = remoteAddress && remoteAddress->getDomain() == SettingsModel::getInstance()->getDefaultDomain() &&
|
||||
remoteAddress->getDomain() == accountParams->getDomain();
|
||||
if (accountParams->getInstantMessagingEncryptionMandatory() && sameDomain) {
|
||||
qDebug() << "Account is in secure mode & domain matches, requesting E2E encryption";
|
||||
chatParams->setBackend(linphone::ChatRoom::Backend::FlexisipChat);
|
||||
params->setSecurityLevel(linphone::Conference::SecurityLevel::EndToEnd);
|
||||
} else if (!accountParams->getInstantMessagingEncryptionMandatory()) {
|
||||
if (SettingsModel::getInstance()->getCreateEndToEndEncryptedMeetingsAndGroupCalls()) {
|
||||
qDebug() << "Account is in interop mode but LIME is available, requesting E2E encryption";
|
||||
chatParams->setBackend(linphone::ChatRoom::Backend::FlexisipChat);
|
||||
params->setSecurityLevel(linphone::Conference::SecurityLevel::EndToEnd);
|
||||
} else {
|
||||
qDebug() << "Account is in interop mode and LIME is available, disabling E2E encryption";
|
||||
chatParams->setBackend(linphone::ChatRoom::Backend::Basic);
|
||||
params->setSecurityLevel(linphone::Conference::SecurityLevel::None);
|
||||
}
|
||||
} else {
|
||||
qDebug() << "Account is in secure mode, can't chat with SIP address of different domain";
|
||||
return nullptr;
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
std::shared_ptr<linphone::ChatRoom> ToolModel::lookupCurrentCallChat(std::shared_ptr<CallModel> callModel) {
|
||||
auto call = callModel->getMonitor();
|
||||
auto conference = callModel->getConference();
|
||||
if (conference) {
|
||||
return conference->getChatRoom();
|
||||
} else {
|
||||
auto core = CoreModel::getInstance()->getCore();
|
||||
auto params = getChatRoomParams(call);
|
||||
auto remoteaddress = call->getRemoteAddress();
|
||||
auto localAddress = call->getCallLog()->getLocalAddress();
|
||||
std::list<std::shared_ptr<linphone::Address>> participants;
|
||||
participants.push_back(remoteaddress->clone());
|
||||
qDebug() << "Looking for chat with local address" << localAddress->asStringUriOnly() << "and participant"
|
||||
<< remoteaddress->asStringUriOnly();
|
||||
auto existingChat = core->searchChatRoom(params, localAddress, nullptr, participants);
|
||||
if (existingChat) qDebug() << "Found existing chat";
|
||||
else qDebug() << "Did not find existing chat";
|
||||
return existingChat;
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<linphone::ChatRoom> ToolModel::createCurrentCallChat(std::shared_ptr<CallModel> callModel) {
|
||||
auto call = callModel->getMonitor();
|
||||
auto remoteAddress = call->getRemoteAddress();
|
||||
std::list<std::shared_ptr<linphone::Address>> participants;
|
||||
participants.push_back(remoteAddress->clone());
|
||||
auto core = CoreModel::getInstance()->getCore();
|
||||
auto params = getChatRoomParams(call);
|
||||
if (!params) {
|
||||
qWarning() << "failed to create chatroom params for call with" << remoteAddress->asStringUriOnly();
|
||||
return nullptr;
|
||||
}
|
||||
auto chatRoom = core->createChatRoom(params, participants);
|
||||
return chatRoom;
|
||||
}
|
||||
|
||||
std::shared_ptr<linphone::ChatRoom> ToolModel::lookupChatForAddress(std::shared_ptr<linphone::Address> remoteAddress) {
|
||||
auto core = CoreModel::getInstance()->getCore();
|
||||
auto account = core->getDefaultAccount();
|
||||
if (!account) return nullptr;
|
||||
auto localAddress = account->getParams()->getIdentityAddress();
|
||||
if (!localAddress || !remoteAddress) return nullptr;
|
||||
|
||||
auto params = getChatRoomParams(nullptr, remoteAddress);
|
||||
std::list<std::shared_ptr<linphone::Address>> participants;
|
||||
participants.push_back(remoteAddress->clone());
|
||||
|
||||
qDebug() << "Looking for chat with local address" << localAddress->asStringUriOnly() << "and participant"
|
||||
<< remoteAddress->asStringUriOnly();
|
||||
auto existingChat = core->searchChatRoom(params, localAddress, nullptr, participants);
|
||||
if (existingChat) qDebug() << "Found existing chat";
|
||||
else qDebug() << "Did not find existing chat";
|
||||
return existingChat;
|
||||
}
|
||||
|
||||
std::shared_ptr<linphone::ChatRoom> ToolModel::createChatForAddress(std::shared_ptr<linphone::Address> remoteAddress) {
|
||||
std::list<std::shared_ptr<linphone::Address>> participants;
|
||||
participants.push_back(remoteAddress->clone());
|
||||
auto core = CoreModel::getInstance()->getCore();
|
||||
auto params = getChatRoomParams(nullptr, remoteAddress);
|
||||
if (!params) {
|
||||
qWarning() << "failed to create chatroom params for address" << remoteAddress->asStringUriOnly();
|
||||
return nullptr;
|
||||
}
|
||||
auto chatRoom = core->createChatRoom(params, participants);
|
||||
return chatRoom;
|
||||
}
|
||||
|
|
@ -81,6 +81,13 @@ public:
|
|||
static QString getOsProduct();
|
||||
static QString computeUserAgent(const std::shared_ptr<linphone::Config> &config);
|
||||
|
||||
static std::shared_ptr<linphone::ConferenceParams>
|
||||
getChatRoomParams(std::shared_ptr<linphone::Call> call, std::shared_ptr<linphone::Address> remoteAddress = nullptr);
|
||||
static std::shared_ptr<linphone::ChatRoom> lookupCurrentCallChat(std::shared_ptr<CallModel> callModel);
|
||||
static std::shared_ptr<linphone::ChatRoom> createCurrentCallChat(std::shared_ptr<CallModel> callModel);
|
||||
static std::shared_ptr<linphone::ChatRoom> lookupChatForAddress(std::shared_ptr<linphone::Address> remoteAddress);
|
||||
static std::shared_ptr<linphone::ChatRoom> createChatForAddress(std::shared_ptr<linphone::Address> remoteAddress);
|
||||
|
||||
private:
|
||||
DECLARE_ABSTRACT_OBJECT
|
||||
};
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@
|
|||
|
||||
#include "core/App.hpp"
|
||||
#include "core/call/CallGui.hpp"
|
||||
#include "core/chat/ChatCore.hpp"
|
||||
#include "core/chat/ChatGui.hpp"
|
||||
#include "core/conference/ConferenceCore.hpp"
|
||||
#include "core/conference/ConferenceInfoCore.hpp"
|
||||
#include "core/conference/ConferenceInfoGui.hpp"
|
||||
|
|
@ -1508,6 +1510,76 @@ Utils::createFriendDeviceVariant(const QString &name, const QString &address, Li
|
|||
return map;
|
||||
}
|
||||
|
||||
VariantObject *Utils::getCurrentCallChat(CallGui *call) {
|
||||
VariantObject *data = new VariantObject("lookupCurrentCallChat");
|
||||
if (!data) return nullptr;
|
||||
if (!call || !call->mCore) return nullptr;
|
||||
data->makeRequest([callModel = call->mCore->getModel(), data]() {
|
||||
if (!callModel) return QVariant();
|
||||
auto linphoneChatRoom = ToolModel::lookupCurrentCallChat(callModel);
|
||||
if (linphoneChatRoom) {
|
||||
auto chatCore = ChatCore::create(linphoneChatRoom);
|
||||
return QVariant::fromValue(new ChatGui(chatCore));
|
||||
} else {
|
||||
qDebug() << "Did not find existing chat room, create one";
|
||||
linphoneChatRoom = ToolModel::createCurrentCallChat(callModel);
|
||||
if (linphoneChatRoom != nullptr) {
|
||||
qDebug() << "Chatroom created with" << callModel->getRemoteAddress()->asStringUriOnly();
|
||||
auto id = linphoneChatRoom->getIdentifier();
|
||||
auto params = linphoneChatRoom->getCurrentParams();
|
||||
auto chatCore = ChatCore::create(linphoneChatRoom);
|
||||
return QVariant::fromValue(new ChatGui(chatCore));
|
||||
} else {
|
||||
qWarning() << "Failed to create 1-1 conversation with"
|
||||
<< callModel->getRemoteAddress()->asStringUriOnly() << "!";
|
||||
//: Failed to create 1-1 conversation with %1 !
|
||||
data->mConnection->invokeToCore([] {
|
||||
showInformationPopup(tr("information_popup_error_title"),
|
||||
tr("information_popup_chatroom_creation_error_message"), false,
|
||||
getCallsWindow());
|
||||
});
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
});
|
||||
data->requestValue();
|
||||
return data;
|
||||
}
|
||||
|
||||
VariantObject *Utils::getChatForAddress(QString address) {
|
||||
VariantObject *data = new VariantObject("lookupCurrentCallChat");
|
||||
if (!data) return nullptr;
|
||||
data->makeRequest([address, data]() {
|
||||
auto linAddr = ToolModel::interpretUrl(address);
|
||||
if (!linAddr) return QVariant();
|
||||
auto linphoneChatRoom = ToolModel::lookupChatForAddress(linAddr);
|
||||
if (linphoneChatRoom) {
|
||||
auto chatCore = ChatCore::create(linphoneChatRoom);
|
||||
return QVariant::fromValue(new ChatGui(chatCore));
|
||||
} else {
|
||||
qDebug() << "Did not find existing chat room, create one";
|
||||
linphoneChatRoom = ToolModel::createChatForAddress(linAddr);
|
||||
if (linphoneChatRoom != nullptr) {
|
||||
qDebug() << "Chatroom created with" << linAddr->asStringUriOnly();
|
||||
auto params = linphoneChatRoom->getCurrentParams();
|
||||
auto chatCore = ChatCore::create(linphoneChatRoom);
|
||||
return QVariant::fromValue(new ChatGui(chatCore));
|
||||
} else {
|
||||
qWarning() << "Failed to create 1-1 conversation with" << linAddr->asStringUriOnly() << "!";
|
||||
//: Failed to create 1-1 conversation with %1 !
|
||||
data->mConnection->invokeToCore([] {
|
||||
showInformationPopup(tr("information_popup_error_title"),
|
||||
tr("information_popup_chatroom_creation_error_message"), false,
|
||||
getCallsWindow());
|
||||
});
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
});
|
||||
data->requestValue();
|
||||
return data;
|
||||
}
|
||||
|
||||
// CLI
|
||||
|
||||
void Utils::runCommandLine(const QString command) {
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ class ConferenceInfoGui;
|
|||
class ConferenceCore;
|
||||
class ParticipantDeviceCore;
|
||||
class DownloadablePayloadTypeCore;
|
||||
class ChatGui;
|
||||
|
||||
class Utils : public QObject, public AbstractObject {
|
||||
Q_OBJECT
|
||||
|
|
@ -88,8 +89,10 @@ public:
|
|||
Q_INVOKABLE static QString createAvatar(const QUrl &fileUrl); // Return the avatar path
|
||||
Q_INVOKABLE static QString formatElapsedTime(int seconds,
|
||||
bool dotsSeparator = true); // Return the elapsed time formated
|
||||
Q_INVOKABLE static QString
|
||||
formatDate(const QDateTime &date, bool includeTime = true, bool includeDateIfToday = true, QString format = ""); // Return the date formated
|
||||
Q_INVOKABLE static QString formatDate(const QDateTime &date,
|
||||
bool includeTime = true,
|
||||
bool includeDateIfToday = true,
|
||||
QString format = ""); // Return the date formated
|
||||
Q_INVOKABLE static QString formatDateElapsedTime(const QDateTime &date);
|
||||
Q_INVOKABLE static QString formatTime(const QDateTime &date); // Return the time formated
|
||||
Q_INVOKABLE static QStringList generateSecurityLettersArray(int arraySize, int correctIndex, QString correctCode);
|
||||
|
|
@ -140,6 +143,8 @@ public:
|
|||
Q_INVOKABLE QList<QVariant> append(const QList<QVariant> a, const QList<QVariant> b);
|
||||
Q_INVOKABLE QString getAddressToDisplay(QVariantList addressList, QString filter, QString defaultAddress);
|
||||
|
||||
Q_INVOKABLE static VariantObject *getCurrentCallChat(CallGui *call);
|
||||
Q_INVOKABLE static VariantObject *getChatForAddress(QString address);
|
||||
// QDir findDirectoryByName(QString startPath, QString name);
|
||||
|
||||
static QString getApplicationProduct();
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ list(APPEND _LINPHONEAPP_QML_FILES
|
|||
view/Control/Popup/Loading/LoadingPopup.qml
|
||||
view/Control/Popup/Notification/Notification.qml
|
||||
view/Control/Popup/Notification/NotificationReceivedCall.qml
|
||||
view/Control/Popup/Notification/NotificationReceivedMessage.qml
|
||||
|
||||
view/Control/Tool/MovableMouseArea.qml
|
||||
view/Control/Tool/Helper/utils.js
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ Control.Button {
|
|||
property bool shadowEnabled: false
|
||||
property var contentImageColor: style?.image?.normal || DefaultStyle.main2_600
|
||||
property var hoveredImageColor: style?.image?.pressed || Qt.darker(contentImageColor, 1.05)
|
||||
property var checkedImageColor: style?.image?.checked || Qt.darker(contentImageColor, 1.1)
|
||||
property var pressedImageColor: style?.image?.pressed || Qt.darker(contentImageColor, 1.1)
|
||||
property bool asynchronous: false
|
||||
spacing: Math.round(5 * DefaultStyle.dp)
|
||||
|
|
@ -126,7 +127,7 @@ Control.Button {
|
|||
imageWidth: mainItem.icon.width
|
||||
imageHeight: mainItem.icon.height
|
||||
colorizationColor: mainItem.checkable && mainItem.checked
|
||||
? mainItem.checkedColor || mainItem.pressedColor
|
||||
? mainItem.checkedImageColor || mainItem.checkedColor || mainItem.pressedColor
|
||||
: mainItem.pressed
|
||||
? mainItem.pressedImageColor
|
||||
: mainItem.hovered
|
||||
|
|
|
|||
|
|
@ -193,7 +193,12 @@ ColumnLayout {
|
|||
button.icon.source: AppIcons.chatTeardropText
|
||||
//: "Message"
|
||||
label: qsTr("contact_message_action")
|
||||
button.onClicked: console.debug("[ContactLayout.qml] TODO : open conversation")
|
||||
button.onClicked: {
|
||||
console.debug("[CallHistoryLayout.qml] Open conversation")
|
||||
if (mainItem.specificAddress === "") {
|
||||
mainWindow.displayChatPage(mainItem.contact.core.defaultAddress)
|
||||
} else mainWindow.displayChatPage(mainItem.specificAddress)
|
||||
}
|
||||
}
|
||||
LabelButton {
|
||||
visible: !mainItem.isConference && SettingsCpp.videoEnabled
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ ColumnLayout {
|
|||
property color panelColor: DefaultStyle.grey_100
|
||||
property alias headerContent: rightPanelHeader.children
|
||||
property alias content: rightPanelContent.children
|
||||
property alias header: rightPanelHeader
|
||||
spacing: 0
|
||||
|
||||
Rectangle {
|
||||
|
|
|
|||
|
|
@ -42,6 +42,11 @@ ListView {
|
|||
// flickDeceleration: 10000
|
||||
spacing: Math.round(10 * DefaultStyle.dp)
|
||||
|
||||
function selectChat(chatGui) {
|
||||
var index = chatProxy.findChatIndex(chatGui)
|
||||
mainItem.currentIndex = index
|
||||
}
|
||||
|
||||
Component.onCompleted: cacheBuffer = Math.max(contentHeight, 0) //contentHeight>0 ? contentHeight : 0// cache all items
|
||||
// remove binding loop
|
||||
onContentHeightChanged: Qt.callLater(function () {
|
||||
|
|
@ -59,12 +64,13 @@ ListView {
|
|||
positionViewAtBeginning() // Stay at beginning
|
||||
}
|
||||
|
||||
onAtYEndChanged: {
|
||||
if (atYEnd && count > 0) {
|
||||
chatProxy.displayMore()
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------
|
||||
onAtYEndChanged: {
|
||||
if (atYEnd && count > 0) {
|
||||
chatProxy.displayMore()
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
function moveToCurrentItem() {
|
||||
if (mainItem.currentIndex >= 0)
|
||||
Utils.updatePosition(mainItem, mainItem)
|
||||
|
|
@ -109,8 +115,8 @@ ListView {
|
|||
component UnreadNotification: Item {
|
||||
id: unreadNotif
|
||||
property int unread: 0
|
||||
width: Math.round(22 * DefaultStyle.dp)
|
||||
height: Math.round(22 * DefaultStyle.dp)
|
||||
width: Math.round(14 * DefaultStyle.dp)
|
||||
height: Math.round(14 * DefaultStyle.dp)
|
||||
visible: unread > 0
|
||||
Rectangle {
|
||||
id: background
|
||||
|
|
@ -123,7 +129,7 @@ ListView {
|
|||
horizontalAlignment: Text.AlignHCenter
|
||||
color: DefaultStyle.grey_0
|
||||
fontSizeMode: Text.Fit
|
||||
font.pixelSize: Typography.p3.pixelSize
|
||||
font.pixelSize: Math.round(10 * DefaultStyle.dp)
|
||||
text: parent.unreadNotif > 100 ? '99+' : unreadNotif.unread
|
||||
}
|
||||
}
|
||||
|
|
@ -155,11 +161,7 @@ ListView {
|
|||
id: historyAvatar
|
||||
property var contactObj: UtilsCpp.findFriendByAddress(modelData.core.peerAddress)
|
||||
contact: contactObj?.value || null
|
||||
onContactChanged: {
|
||||
if (contact) console.log("found contact", contact.core.defaultAddress)
|
||||
else console.log("no contact for peer address", modelData.core.peerAddress, modelData.core.avatarUri)
|
||||
}
|
||||
displayNameVal: contact ? undefined : modelData.core.avatarUri
|
||||
displayNameVal: contact ? "" : modelData.core.avatarUri
|
||||
// secured: securityLevel === LinphoneEnums.SecurityLevel.EndToEndEncryptedAndVerified
|
||||
Layout.preferredWidth: Math.round(45 * DefaultStyle.dp)
|
||||
Layout.preferredHeight: Math.round(45 * DefaultStyle.dp)
|
||||
|
|
@ -208,6 +210,7 @@ ListView {
|
|||
}
|
||||
|
||||
RowLayout {
|
||||
Item {Layout.fillWidth: true}
|
||||
UnreadNotification {
|
||||
id: unreadCount
|
||||
unread: modelData.core.unreadMessagesCount
|
||||
|
|
@ -230,10 +233,8 @@ ListView {
|
|||
anchors.fill: parent
|
||||
opacity: 0.7
|
||||
radius: Math.round(8 * DefaultStyle.dp)
|
||||
color: mainItem.currentIndex
|
||||
=== index ? DefaultStyle.main2_200 : DefaultStyle.main2_100
|
||||
visible: mainItem.lastMouseContainsIndex === index
|
||||
|| mainItem.currentIndex === index
|
||||
color: mainItem.currentIndex === index ? DefaultStyle.main2_200 : DefaultStyle.main2_100
|
||||
visible: mainItem.lastMouseContainsIndex === index || mainItem.currentIndex === index
|
||||
}
|
||||
onPressed: {
|
||||
mainItem.currentIndex = model.index
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@ ListView {
|
|||
chatGui: mainItem.chat
|
||||
}
|
||||
|
||||
header: Item {
|
||||
height: Math.round(18 * DefaultStyle.dp)
|
||||
}
|
||||
|
||||
delegate: ChatMessage {
|
||||
id: chatMessage
|
||||
width: Math.min(implicitWidth, Math.round(mainItem.width * (3/4)))
|
||||
|
|
|
|||
|
|
@ -170,6 +170,10 @@ FocusScope {
|
|||
style: ButtonStyle.grey
|
||||
KeyNavigation.left: videoCallButton
|
||||
KeyNavigation.right: callButton
|
||||
onClicked: {
|
||||
console.debug("[ContactListItem.qml] Open conversation")
|
||||
mainWindow.displayChatPage(mainItem.addressFromFilter)
|
||||
}
|
||||
}
|
||||
}
|
||||
PopupButton {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import Qt.labs.platform
|
|||
|
||||
|
||||
// =============================================================================
|
||||
Window {
|
||||
Window {
|
||||
id: mainItem
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -0,0 +1,118 @@
|
|||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Linphone
|
||||
import UtilsCpp
|
||||
import QtQuick.Controls as Control
|
||||
import 'qrc:/qt/qml/Linphone/view/Style/buttonStyle.js' as ButtonStyle
|
||||
|
||||
// =============================================================================
|
||||
|
||||
Notification {
|
||||
id: mainItem
|
||||
radius: Math.round(20 * DefaultStyle.dp)
|
||||
backgroundColor: DefaultStyle.grey_600
|
||||
backgroundOpacity: 0.8
|
||||
overriddenWidth: Math.round(400 * DefaultStyle.dp)
|
||||
overriddenHeight: content.height
|
||||
|
||||
property string avatarUri: notificationData && notificationData.avatarUri
|
||||
property string chatRoomName: notificationData && notificationData.chatRoomName
|
||||
property string remoteAddress: notificationData && notificationData.remoteAddress
|
||||
property string message: notificationData && notificationData.message
|
||||
|
||||
Popup {
|
||||
id: content
|
||||
visible: mainItem.visible
|
||||
width: parent.width
|
||||
leftPadding: Math.round(18 * DefaultStyle.dp)
|
||||
rightPadding: Math.round(18 * DefaultStyle.dp)
|
||||
topPadding: Math.round(9 * DefaultStyle.dp)
|
||||
bottomPadding: Math.round(18 * DefaultStyle.dp)
|
||||
background: Item{}
|
||||
contentItem: ColumnLayout {
|
||||
spacing: Math.round(9 * DefaultStyle.dp)
|
||||
RowLayout {
|
||||
spacing: Math.round(4 * DefaultStyle.dp)
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Image {
|
||||
Layout.preferredWidth: Math.round(12 * DefaultStyle.dp)
|
||||
Layout.preferredHeight: Math.round(12 * DefaultStyle.dp)
|
||||
source: AppIcons.logo
|
||||
}
|
||||
Text {
|
||||
text: "Linphone"
|
||||
color: DefaultStyle.grey_0
|
||||
font {
|
||||
pixelSize: Math.round(12 * DefaultStyle.dp)
|
||||
weight: Typography.b3.weight
|
||||
capitalization: Font.Capitalize
|
||||
}
|
||||
}
|
||||
}
|
||||
ColumnLayout {
|
||||
spacing: Math.round(14 * DefaultStyle.dp)
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
RowLayout {
|
||||
spacing: Math.round(10 * DefaultStyle.dp)
|
||||
Avatar {
|
||||
Layout.preferredWidth: Math.round(45 * DefaultStyle.dp)
|
||||
Layout.preferredHeight: Math.round(45 * DefaultStyle.dp)
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
property var contactObj: UtilsCpp.findFriendByAddress(mainItem.remoteAddress)
|
||||
contact: contactObj?.value || null
|
||||
displayNameVal: contact ? "" : mainItem.avatarUri
|
||||
}
|
||||
ColumnLayout {
|
||||
spacing: 0
|
||||
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
|
||||
Layout.preferredHeight: Math.round(60 * DefaultStyle.dp)
|
||||
color: DefaultStyle.main2_400
|
||||
radius: Math.round(5 * DefaultStyle.dp)
|
||||
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
|
||||
maximumLineCount: 2
|
||||
color: DefaultStyle.grey_1000
|
||||
font {
|
||||
pixelSize: Typography.p1s.pixelSize
|
||||
weight: Typography.p1s.weight
|
||||
italic: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -12,21 +12,26 @@ import 'qrc:/qt/qml/Linphone/view/Style/buttonStyle.js' as ButtonStyle
|
|||
RowLayout {
|
||||
id: mainItem
|
||||
property ChatGui chat
|
||||
property CallGui call
|
||||
property alias callHeaderContent: splitPanel.headerContent
|
||||
spacing: 0
|
||||
MainRightPanel {
|
||||
id: splitPanel
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
panelColor: DefaultStyle.grey_0
|
||||
header.visible: !mainItem.call
|
||||
clip: true
|
||||
headerContent: [
|
||||
RowLayout {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Math.round(31 * DefaultStyle.dp)
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent?.left
|
||||
anchors.leftMargin: mainItem.call ? 0 : Math.round(31 * DefaultStyle.dp)
|
||||
anchors.verticalCenter: parent?.verticalCenter
|
||||
spacing: Math.round(12 * DefaultStyle.dp)
|
||||
Avatar {
|
||||
property var contactObj: mainItem.chat ? UtilsCpp.findFriendByAddress(mainItem.chat.core.peerAddress) : null
|
||||
property var contactObj: mainItem.chat ? UtilsCpp.findFriendByAddress(mainItem.chat?.core.peerAddress) : null
|
||||
contact: contactObj?.value || null
|
||||
displayNameVal: contact ? "" : mainItem.chat.core.avatarUri
|
||||
Layout.preferredWidth: Math.round(45 * DefaultStyle.dp)
|
||||
Layout.preferredHeight: Math.round(45 * DefaultStyle.dp)
|
||||
}
|
||||
|
|
@ -38,6 +43,7 @@ RowLayout {
|
|||
font {
|
||||
pixelSize: Typography.h4.pixelSize
|
||||
weight: Math.round(400 * DefaultStyle.dp)
|
||||
capitalization: Font.Capitalize
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -51,7 +57,7 @@ RowLayout {
|
|||
}
|
||||
BigButton {
|
||||
style: ButtonStyle.noBackground
|
||||
icon.source: AppIcons.camera
|
||||
icon.source: AppIcons.videoCamera
|
||||
}
|
||||
BigButton {
|
||||
style: ButtonStyle.noBackground
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ Item {
|
|||
signal openCallHistory
|
||||
signal openNumPadRequest
|
||||
signal displayContactRequested(string contactAddress)
|
||||
signal displayChatRequested(string contactAddress)
|
||||
signal createContactRequested(string name, string address)
|
||||
signal accountRemoved
|
||||
|
||||
|
|
@ -41,6 +42,10 @@ Item {
|
|||
tabbar.currentIndex = 1
|
||||
mainItem.displayContactRequested(contactAddress)
|
||||
}
|
||||
function displayChatPage(contactAddress) {
|
||||
tabbar.currentIndex = 2
|
||||
mainItem.displayChatRequested(contactAddress)
|
||||
}
|
||||
|
||||
function createContact(name, address) {
|
||||
tabbar.currentIndex = 1
|
||||
|
|
@ -616,7 +621,17 @@ Item {
|
|||
}
|
||||
}
|
||||
}
|
||||
ChatPage{}
|
||||
ChatPage {
|
||||
id: chatPage
|
||||
Connections {
|
||||
target: mainItem
|
||||
function onDisplayChatRequested(contactAddress) {
|
||||
console.log("display chat requested, open with address", contactAddress)
|
||||
chatPage.remoteAddress = ""
|
||||
chatPage.remoteAddress = contactAddress
|
||||
}
|
||||
}
|
||||
}
|
||||
MeetingPage {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -532,12 +532,9 @@ AbstractMainPage {
|
|||
onClicked: {
|
||||
detailOptions.close()
|
||||
if (contactDetail.isLocalFriend)
|
||||
mainWindow.displayContactPage(
|
||||
contactDetail.contactAddress)
|
||||
mainWindow.displayContactPage(contactDetail.contactAddress)
|
||||
else
|
||||
mainItem.createContactRequested(
|
||||
contactDetail.contactName,
|
||||
contactDetail.contactAddress)
|
||||
mainItem.createContactRequested(contactDetail.contactName, contactDetail.contactAddress)
|
||||
}
|
||||
}
|
||||
IconLabelButton {
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ Control.Page {
|
|||
header: Control.Control {
|
||||
id: pageHeader
|
||||
width: mainItem.width
|
||||
height: Math.round(56 * DefaultStyle.dp)
|
||||
height: Math.round(67 * DefaultStyle.dp)
|
||||
leftPadding: Math.round(10 * DefaultStyle.dp)
|
||||
rightPadding: Math.round(10 * DefaultStyle.dp)
|
||||
background: Rectangle {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,12 @@ AbstractMainPage {
|
|||
|
||||
property var selectedChatGui
|
||||
|
||||
property string remoteAddress
|
||||
onRemoteAddressChanged: console.log("ChatPage : remote address changed :", remoteAddress)
|
||||
property var remoteChatObj: UtilsCpp.getChatForAddress(remoteAddress)
|
||||
property ChatGui remoteChat: remoteChatObj ? remoteChatObj.value : null
|
||||
onRemoteChatChanged: if (remoteChat) selectedChatGui = remoteChat
|
||||
|
||||
onSelectedChatGuiChanged: {
|
||||
if (selectedChatGui)
|
||||
rightPanelStackView.replace(currentChatComp,
|
||||
|
|
@ -151,6 +157,11 @@ AbstractMainPage {
|
|||
onCountChanged: {
|
||||
mainItem.selectedChatGui = model.getAt(currentIndex)
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: mainItem
|
||||
onSelectedChatGuiChanged: chatListView.selectChat(mainItem.selectedChatGui)
|
||||
}
|
||||
}
|
||||
}
|
||||
ScrollBar {
|
||||
|
|
|
|||
|
|
@ -411,9 +411,7 @@ FriendGui{
|
|||
height: Math.round(56 * DefaultStyle.dp)
|
||||
button.icon.width: Math.round(24 * DefaultStyle.dp)
|
||||
button.icon.height: Math.round(24 * DefaultStyle.dp)
|
||||
button.onClicked: mainWindow.startCallWithContact(
|
||||
contactDetail.contact,
|
||||
false, mainItem)
|
||||
button.onClicked: mainWindow.startCallWithContact(contactDetail.contact, false, mainItem)
|
||||
}
|
||||
LabelButton {
|
||||
button.icon.source: AppIcons.chatTeardropText
|
||||
|
|
@ -424,8 +422,10 @@ FriendGui{
|
|||
height: Math.round(56 * DefaultStyle.dp)
|
||||
button.icon.width: Math.round(24 * DefaultStyle.dp)
|
||||
button.icon.height: Math.round(24 * DefaultStyle.dp)
|
||||
button.onClicked: console.debug(
|
||||
"[ContactLayout.qml] TODO : open conversation")
|
||||
button.onClicked: {
|
||||
console.debug("[ContactLayout.qml] Open conversation")
|
||||
mainWindow.displayChatPage(contactDetail.contact.core.defaultAddress)
|
||||
}
|
||||
}
|
||||
LabelButton {
|
||||
visible: SettingsCpp.videoEnabled
|
||||
|
|
@ -436,9 +436,7 @@ FriendGui{
|
|||
height: Math.round(56 * DefaultStyle.dp)
|
||||
button.icon.width: Math.round(24 * DefaultStyle.dp)
|
||||
button.icon.height: Math.round(24 * DefaultStyle.dp)
|
||||
button.onClicked: mainWindow.startCallWithContact(
|
||||
contactDetail.contact,
|
||||
true, mainItem)
|
||||
button.onClicked: mainWindow.startCallWithContact(contactDetail.contact, true, mainItem)
|
||||
}
|
||||
}
|
||||
bannerContent: [
|
||||
|
|
@ -636,7 +634,7 @@ FriendGui{
|
|||
EffectImage {
|
||||
Layout.preferredWidth: Math.round(24 * DefaultStyle.dp)
|
||||
Layout.preferredHeight: Math.round(24 * DefaultStyle.dp)
|
||||
source: AppIcons.shareNetwork
|
||||
imageSource: AppIcons.shareNetwork
|
||||
colorizationColor: DefaultStyle.main2_600
|
||||
}
|
||||
Text {
|
||||
|
|
|
|||
|
|
@ -620,6 +620,19 @@ AbstractWindow {
|
|||
contentStackView.initialItem: callListPanel
|
||||
headerValidateButtonText: qsTr("add")
|
||||
|
||||
Binding on topPadding {
|
||||
when: rightPanel.contentStackView.currentItem.objectName === "chatPanel"
|
||||
value: 0
|
||||
}
|
||||
Binding on leftPadding {
|
||||
when: rightPanel.contentStackView.currentItem.objectName === "chatPanel"
|
||||
value: 0
|
||||
}
|
||||
Binding on rightPadding {
|
||||
when: rightPanel.contentStackView.currentItem.objectName == "chatPanel"
|
||||
value: 0
|
||||
}
|
||||
|
||||
Item {
|
||||
id: numericPadContainer
|
||||
anchors.bottom: parent.bottom
|
||||
|
|
@ -836,6 +849,28 @@ AbstractWindow {
|
|||
}
|
||||
}
|
||||
}
|
||||
Component {
|
||||
id: chatPanel
|
||||
Item {
|
||||
id: chatPanelContent
|
||||
objectName: "chatPanel"
|
||||
Control.StackView.onActivated: {
|
||||
rightPanel.customHeaderButtons = chatView.callHeaderContent
|
||||
rightPanel.headerTitleText = ""
|
||||
}
|
||||
Keys.onEscapePressed: event => {
|
||||
rightPanel.visible = false
|
||||
event.accepted = true
|
||||
}
|
||||
SelectedChatView {
|
||||
id: chatView
|
||||
anchors.fill: parent
|
||||
call: mainWindow.call
|
||||
property var chatObj: UtilsCpp.getCurrentCallChat(mainWindow.call)
|
||||
chat: chatObj ? chatObj.value : null
|
||||
}
|
||||
}
|
||||
}
|
||||
Component {
|
||||
id: settingsPanel
|
||||
Item {
|
||||
|
|
@ -1313,6 +1348,23 @@ AbstractWindow {
|
|||
}
|
||||
}
|
||||
}
|
||||
CheckableButton {
|
||||
iconUrl: AppIcons.chatTeardropText
|
||||
//: Open chat…
|
||||
ToolTip.text: qsTr("call_open_chat_hint")
|
||||
Layout.preferredWidth: Math.round(55 * DefaultStyle.dp)
|
||||
Layout.preferredHeight: Math.round(55 * DefaultStyle.dp)
|
||||
icon.width: Math.round(32 * DefaultStyle.dp)
|
||||
icon.height: Math.round(32 * DefaultStyle.dp)
|
||||
onCheckedChanged: {
|
||||
if (checked) {
|
||||
rightPanel.visible = true
|
||||
rightPanel.replace(chatPanel)
|
||||
} else {
|
||||
rightPanel.visible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
CheckableButton {
|
||||
visible: false
|
||||
checkable: false
|
||||
|
|
|
|||
|
|
@ -56,6 +56,10 @@ AbstractWindow {
|
|||
openMainPage()
|
||||
mainWindowStackView.currentItem.displayContactPage(contactAddress)
|
||||
}
|
||||
function displayChatPage(contactAddress) {
|
||||
openMainPage()
|
||||
mainWindowStackView.currentItem.displayChatPage(contactAddress)
|
||||
}
|
||||
function transferCallSucceed() {
|
||||
openMainPage()
|
||||
//: "Appel transféré"
|
||||
|
|
|
|||
|
|
@ -121,7 +121,8 @@
|
|||
},
|
||||
image: {
|
||||
normal: Linphone.DefaultStyle.grey_0,
|
||||
pressed: Linphone.DefaultStyle.grey_0
|
||||
pressed: Linphone.DefaultStyle.grey_0,
|
||||
checked: Linphone.DefaultStyle.grey_0
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue