mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-01-17 03:18:07 +00:00
Send message, composing notification
This commit is contained in:
parent
bdff2bddcd
commit
ecd9373df9
17 changed files with 363 additions and 124 deletions
|
|
@ -162,6 +162,37 @@ void ChatCore::setSelf(QSharedPointer<ChatCore> me) {
|
|||
mChatModelConnection->invokeToCore([this, message]() { setLastMessageInHistory(message); });
|
||||
});
|
||||
});
|
||||
mChatModelConnection->makeConnectToCore(&ChatCore::lSendTextMessage, [this](QString message) {
|
||||
mChatModelConnection->invokeToModel([this, message]() {
|
||||
auto linMessage = mChatModel->createTextMessageFromText(message);
|
||||
linMessage->send();
|
||||
});
|
||||
});
|
||||
mChatModelConnection->makeConnectToModel(
|
||||
&ChatModel::chatMessageSending, [this](const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
||||
const std::shared_ptr<const linphone::EventLog> &eventLog) {
|
||||
auto message = eventLog->getChatMessage();
|
||||
if (message) {
|
||||
auto newMessage = ChatMessageCore::create(message);
|
||||
mChatModelConnection->invokeToCore([this, newMessage]() { appendMessageToMessageList(newMessage); });
|
||||
}
|
||||
});
|
||||
mChatModelConnection->makeConnectToCore(
|
||||
&ChatCore::lCompose, [this]() { mChatModelConnection->invokeToModel([this]() { mChatModel->compose(); }); });
|
||||
mChatModelConnection->makeConnectToModel(
|
||||
&ChatModel::isComposingReceived,
|
||||
[this](const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
||||
const std::shared_ptr<const linphone::Address> &remoteAddress, bool isComposing) {
|
||||
if (mChatModel->getMonitor() != chatRoom) return;
|
||||
QString name = isComposing ? ToolModel::getDisplayName(remoteAddress->clone()) : QString();
|
||||
auto remoteAddr = remoteAddress->clone();
|
||||
remoteAddr->clean();
|
||||
mChatModelConnection->invokeToCore(
|
||||
[this, name, address = Utils::coreStringToAppString(remoteAddr->asStringUriOnly())]() {
|
||||
setComposingName(name);
|
||||
setComposingAddress(address);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
QDateTime ChatCore::getLastUpdatedTime() const {
|
||||
|
|
@ -275,6 +306,28 @@ void ChatCore::clearMessagesList() {
|
|||
emit messageListChanged();
|
||||
}
|
||||
|
||||
QString ChatCore::getComposingName() const {
|
||||
return mComposingName;
|
||||
}
|
||||
|
||||
void ChatCore::setComposingName(QString composingName) {
|
||||
if (mComposingAddress != composingName) {
|
||||
mComposingName = composingName;
|
||||
emit composingUserChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void ChatCore::setComposingAddress(QString composingAddress) {
|
||||
if (mComposingAddress != composingAddress) {
|
||||
mComposingAddress = composingAddress;
|
||||
emit composingUserChanged();
|
||||
}
|
||||
}
|
||||
|
||||
QString ChatCore::getComposingAddress() const {
|
||||
return mComposingAddress;
|
||||
}
|
||||
|
||||
std::shared_ptr<ChatModel> ChatCore::getModel() const {
|
||||
return mChatModel;
|
||||
}
|
||||
|
|
@ -43,6 +43,8 @@ public:
|
|||
lastMessageInHistoryChanged)
|
||||
Q_PROPERTY(int unreadMessagesCount READ getUnreadMessagesCount WRITE setUnreadMessagesCount NOTIFY
|
||||
unreadMessagesCountChanged)
|
||||
Q_PROPERTY(QString composingName READ getComposingName WRITE setComposingName NOTIFY composingUserChanged)
|
||||
Q_PROPERTY(QString composingAddress READ getComposingAddress WRITE setComposingAddress NOTIFY composingUserChanged)
|
||||
// Q_PROPERTY(VideoStats videoStats READ getVideoStats WRITE setVideoStats NOTIFY videoStatsChanged)
|
||||
|
||||
// Should be call from model Thread. Will be automatically in App thread after initialization
|
||||
|
|
@ -78,6 +80,11 @@ public:
|
|||
QString getAvatarUri() const;
|
||||
void setAvatarUri(QString avatarUri);
|
||||
|
||||
QString getComposingName() const;
|
||||
QString getComposingAddress() const;
|
||||
void setComposingName(QString composingName);
|
||||
void setComposingAddress(QString composingAddress);
|
||||
|
||||
std::shared_ptr<ChatModel> getModel() const;
|
||||
|
||||
signals:
|
||||
|
|
@ -89,6 +96,7 @@ signals:
|
|||
void messageListChanged();
|
||||
void avatarUriChanged();
|
||||
void deleted();
|
||||
void composingUserChanged();
|
||||
|
||||
void lDeleteMessage();
|
||||
void lDelete();
|
||||
|
|
@ -96,6 +104,8 @@ signals:
|
|||
void lMarkAsRead();
|
||||
void lUpdateLastMessage();
|
||||
void lUpdateUnreadCount();
|
||||
void lSendTextMessage(QString message);
|
||||
void lCompose();
|
||||
|
||||
private:
|
||||
QString id;
|
||||
|
|
@ -106,6 +116,8 @@ private:
|
|||
QString mIdentifier;
|
||||
QString mAvatarUri;
|
||||
int mUnreadMessagesCount;
|
||||
QString mComposingName;
|
||||
QString mComposingAddress;
|
||||
std::shared_ptr<ChatModel> mChatModel;
|
||||
QList<QSharedPointer<ChatMessageCore>> mChatMessageList;
|
||||
QSharedPointer<SafeConnection<ChatCore, ChatModel>> mChatModelConnection;
|
||||
|
|
|
|||
|
|
@ -45,6 +45,14 @@ ChatMessageCore::ChatMessageCore(const std::shared_ptr<linphone::ChatMessage> &c
|
|||
mIsRemoteMessage = !from->weakEqual(to);
|
||||
mPeerAddress = Utils::coreStringToAppString(chatmessage->getPeerAddress()->asStringUriOnly());
|
||||
mPeerName = ToolModel::getDisplayName(chatmessage->getPeerAddress()->clone());
|
||||
auto fromAddress = chatmessage->getFromAddress()->clone();
|
||||
fromAddress->clean();
|
||||
mFromAddress = Utils::coreStringToAppString(fromAddress->asStringUriOnly());
|
||||
mFromName = ToolModel::getDisplayName(chatmessage->getFromAddress()->clone());
|
||||
|
||||
auto chatroom = chatmessage->getChatRoom();
|
||||
mIsFromChatGroup = chatroom->hasCapability((int)linphone::ChatRoom::Capabilities::Conference) &&
|
||||
!chatroom->hasCapability((int)linphone::ChatRoom::Capabilities::OneToOne);
|
||||
}
|
||||
|
||||
ChatMessageCore::~ChatMessageCore() {
|
||||
|
|
@ -91,15 +99,24 @@ QString ChatMessageCore::getPeerName() const {
|
|||
return mPeerName;
|
||||
}
|
||||
|
||||
QString ChatMessageCore::getFromAddress() const {
|
||||
return mFromAddress;
|
||||
}
|
||||
|
||||
QString ChatMessageCore::getFromName() const {
|
||||
return mFromName;
|
||||
}
|
||||
|
||||
QString ChatMessageCore::getToAddress() const {
|
||||
return mToAddress;
|
||||
}
|
||||
|
||||
bool ChatMessageCore::isRemoteMessage() const {
|
||||
return mIsRemoteMessage;
|
||||
}
|
||||
|
||||
void ChatMessageCore::setIsRemoteMessage(bool isRemote) {
|
||||
if (mIsRemoteMessage != isRemote) {
|
||||
mIsRemoteMessage = isRemote;
|
||||
emit isRemoteMessageChanged(isRemote);
|
||||
}
|
||||
bool ChatMessageCore::isFromChatGroup() const {
|
||||
return mIsFromChatGroup;
|
||||
}
|
||||
|
||||
std::shared_ptr<ChatMessageModel> ChatMessageCore::getModel() const {
|
||||
|
|
|
|||
|
|
@ -36,8 +36,12 @@ class ChatMessageCore : public QObject, public AbstractObject {
|
|||
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 fromAddress READ getFromAddress CONSTANT)
|
||||
Q_PROPERTY(QString toAddress READ getToAddress CONSTANT)
|
||||
Q_PROPERTY(QString peerName READ getPeerName CONSTANT)
|
||||
Q_PROPERTY(bool isRemoteMessage READ isRemoteMessage WRITE setIsRemoteMessage NOTIFY isRemoteMessageChanged)
|
||||
Q_PROPERTY(QString fromName READ getFromName CONSTANT)
|
||||
Q_PROPERTY(bool isRemoteMessage READ isRemoteMessage CONSTANT)
|
||||
Q_PROPERTY(bool isFromChatGroup READ isFromChatGroup CONSTANT)
|
||||
|
||||
public:
|
||||
static QSharedPointer<ChatMessageCore> create(const std::shared_ptr<linphone::ChatMessage> &chatmessage);
|
||||
|
|
@ -53,9 +57,12 @@ public:
|
|||
|
||||
QString getPeerAddress() const;
|
||||
QString getPeerName() const;
|
||||
QString getFromAddress() const;
|
||||
QString getFromName() const;
|
||||
QString getToAddress() const;
|
||||
|
||||
bool isRemoteMessage() const;
|
||||
void setIsRemoteMessage(bool isRemote);
|
||||
bool isFromChatGroup() const;
|
||||
|
||||
std::shared_ptr<ChatMessageModel> getModel() const;
|
||||
|
||||
|
|
@ -70,9 +77,13 @@ signals:
|
|||
private:
|
||||
DECLARE_ABSTRACT_OBJECT QString mText;
|
||||
QString mPeerAddress;
|
||||
QString mFromAddress;
|
||||
QString mToAddress;
|
||||
QString mFromName;
|
||||
QString mPeerName;
|
||||
QDateTime mTimestamp;
|
||||
bool mIsRemoteMessage = false;
|
||||
bool mIsFromChatGroup = false;
|
||||
std::shared_ptr<ChatMessageModel> mChatMessageModel;
|
||||
QSharedPointer<SafeConnection<ChatMessageCore, ChatMessageModel>> mChatMessageModelConnection;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -46,19 +46,30 @@ void ChatMessageProxy::setSourceModel(QAbstractItemModel *model) {
|
|||
sort(0);
|
||||
}
|
||||
|
||||
ChatGui* ChatMessageProxy::getChatGui() {
|
||||
ChatGui *ChatMessageProxy::getChatGui() {
|
||||
auto model = getListModel<ChatMessageList>();
|
||||
if (!mChatGui && model) mChatGui = model->getChat();
|
||||
return mChatGui;
|
||||
}
|
||||
|
||||
void ChatMessageProxy::setChatGui(ChatGui* chat) {
|
||||
void ChatMessageProxy::setChatGui(ChatGui *chat) {
|
||||
getListModel<ChatMessageList>()->setChatGui(chat);
|
||||
}
|
||||
|
||||
ChatMessageGui *ChatMessageProxy::getChatMessageAtIndex(int i) {
|
||||
auto model = getListModel<ChatMessageList>();
|
||||
auto sourceIndex = mapToSource(index(i, 0)).row();
|
||||
if (model) {
|
||||
auto chat = model->getAt<ChatMessageCore>(sourceIndex);
|
||||
if (chat) return new ChatMessageGui(chat);
|
||||
else return nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool ChatMessageProxy::SortFilterList::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const {
|
||||
// auto l = getItemAtSource<ChatMessageList, ChatMessageCore>(sourceRow);
|
||||
// return l != nullptr;
|
||||
// auto l = getItemAtSource<ChatMessageList, ChatMessageCore>(sourceRow);
|
||||
// return l != nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@
|
|||
#ifndef CHAT_MESSAGE_PROXY_H_
|
||||
#define CHAT_MESSAGE_PROXY_H_
|
||||
|
||||
#include "core/proxy/LimitProxy.hpp"
|
||||
#include "ChatMessageList.hpp"
|
||||
#include "core/proxy/LimitProxy.hpp"
|
||||
#include "tool/AbstractObject.hpp"
|
||||
|
||||
// =============================================================================
|
||||
|
|
@ -31,7 +31,7 @@ class ChatGui;
|
|||
|
||||
class ChatMessageProxy : public LimitProxy, public AbstractObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(ChatGui* chatGui READ getChatGui WRITE setChatGui NOTIFY chatChanged)
|
||||
Q_PROPERTY(ChatGui *chatGui READ getChatGui WRITE setChatGui NOTIFY chatChanged)
|
||||
|
||||
public:
|
||||
DECLARE_SORTFILTER_CLASS()
|
||||
|
|
@ -39,17 +39,19 @@ public:
|
|||
ChatMessageProxy(QObject *parent = Q_NULLPTR);
|
||||
~ChatMessageProxy();
|
||||
|
||||
ChatGui* getChatGui();
|
||||
void setChatGui(ChatGui* chat);
|
||||
ChatGui *getChatGui();
|
||||
void setChatGui(ChatGui *chat);
|
||||
|
||||
void setSourceModel(QAbstractItemModel *sourceModel) override;
|
||||
|
||||
Q_INVOKABLE ChatMessageGui *getChatMessageAtIndex(int index);
|
||||
|
||||
signals:
|
||||
void chatChanged();
|
||||
|
||||
protected:
|
||||
QSharedPointer<ChatMessageList> mList;
|
||||
ChatGui* mChatGui = nullptr;
|
||||
ChatGui *mChatGui = nullptr;
|
||||
DECLARE_ABSTRACT_OBJECT
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -119,6 +119,14 @@ void ChatModel::deleteChatRoom() {
|
|||
emit deleted();
|
||||
}
|
||||
|
||||
std::shared_ptr<linphone::ChatMessage> ChatModel::createTextMessageFromText(QString text) {
|
||||
return mMonitor->createMessageFromUtf8(Utils::appStringToCoreString(text));
|
||||
}
|
||||
|
||||
void ChatModel::compose() {
|
||||
mMonitor->compose();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------//
|
||||
|
||||
void ChatModel::onIsComposingReceived(const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ public:
|
|||
QString getIdentifier() const;
|
||||
void deleteHistory();
|
||||
void deleteChatRoom();
|
||||
std::shared_ptr<linphone::ChatMessage> createTextMessageFromText(QString text);
|
||||
void compose();
|
||||
|
||||
signals:
|
||||
void historyDeleted();
|
||||
|
|
|
|||
|
|
@ -48,6 +48,14 @@ QString ChatMessageModel::getPeerAddress() const {
|
|||
return Utils::coreStringToAppString(mMonitor->getPeerAddress()->asStringUriOnly());
|
||||
}
|
||||
|
||||
QString ChatMessageModel::getFromAddress() const {
|
||||
return Utils::coreStringToAppString(mMonitor->getFromAddress()->asStringUriOnly());
|
||||
}
|
||||
|
||||
QString ChatMessageModel::getToAddress() const {
|
||||
return Utils::coreStringToAppString(mMonitor->getToAddress()->asStringUriOnly());
|
||||
}
|
||||
|
||||
QDateTime ChatMessageModel::getTimestamp() const {
|
||||
return QDateTime::fromSecsSinceEpoch(mMonitor->getTime());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ public:
|
|||
QDateTime getTimestamp() const;
|
||||
|
||||
QString getPeerAddress() const;
|
||||
QString getFromAddress() const;
|
||||
QString getToAddress() const;
|
||||
|
||||
void deleteMessageFromChatRoom();
|
||||
|
||||
|
|
|
|||
|
|
@ -8,115 +8,136 @@ import SettingsCpp
|
|||
import "qrc:/qt/qml/Linphone/view/Style/buttonStyle.js" as ButtonStyle
|
||||
import "qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js" as Utils
|
||||
|
||||
Control.Control {
|
||||
|
||||
RowLayout {
|
||||
id: mainItem
|
||||
property color backgroundColor
|
||||
property bool isRemoteMessage
|
||||
property bool isFirstMessage
|
||||
|
||||
property string imgUrl
|
||||
property string contentText
|
||||
spacing: 0
|
||||
|
||||
property ChatMessageGui chatMessage
|
||||
property string fromAddress: chatMessage? chatMessage.core.fromAddress : ""
|
||||
property bool isRemoteMessage: chatMessage? chatMessage.core.isRemoteMessage : false
|
||||
property bool isFromChatGroup: chatMessage? chatMessage.core.isFromChatGroup : false
|
||||
|
||||
topPadding: Math.round(12 * DefaultStyle.dp)
|
||||
bottomPadding: Math.round(12 * DefaultStyle.dp)
|
||||
leftPadding: Math.round(18 * DefaultStyle.dp)
|
||||
rightPadding: Math.round(18 * DefaultStyle.dp)
|
||||
|
||||
signal messageDeletionRequested()
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.RightButton
|
||||
onClicked: (mouse) => {
|
||||
console.log("message clicked")
|
||||
if (mouse.button === Qt.RightButton) {
|
||||
optionsMenu.x = mouse.x
|
||||
optionsMenu.open()
|
||||
Avatar {
|
||||
id: avatar
|
||||
visible: mainItem.isFromChatGroup
|
||||
opacity: mainItem.isRemoteMessage && mainItem.isFirstMessage ? 1 : 0
|
||||
Layout.preferredWidth: 26 * DefaultStyle.dp
|
||||
Layout.preferredHeight: 26 * DefaultStyle.dp
|
||||
Layout.alignment: Qt.AlignTop
|
||||
Layout.topMargin: isFirstMessage ? 16 * DefaultStyle.dp : 0
|
||||
_address: chatMessage ? chatMessage.core.fromAddress : ""
|
||||
}
|
||||
Control.Control {
|
||||
Layout.topMargin: isFirstMessage ? 16 * DefaultStyle.dp : 0
|
||||
Layout.leftMargin: mainItem.isFromChatGroup ? Math.round(9 * DefaultStyle.dp) : 0
|
||||
Layout.preferredWidth: Math.min(implicitWidth, mainItem.maxWidth - avatar.implicitWidth)
|
||||
// Layout.topMargin: name.visible ? Math.round(7 * DefaultStyle.dp) : 0
|
||||
topPadding: Math.round(12 * DefaultStyle.dp)
|
||||
bottomPadding: Math.round(12 * DefaultStyle.dp)
|
||||
leftPadding: Math.round(18 * DefaultStyle.dp)
|
||||
rightPadding: Math.round(18 * DefaultStyle.dp)
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.RightButton
|
||||
onClicked: (mouse) => {
|
||||
console.log("message clicked")
|
||||
if (mouse.button === Qt.RightButton) {
|
||||
optionsMenu.x = mouse.x
|
||||
optionsMenu.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Popup {
|
||||
id: optionsMenu
|
||||
Popup {
|
||||
id: optionsMenu
|
||||
background: Item {
|
||||
anchors.fill: parent
|
||||
Rectangle {
|
||||
id: popupBackground
|
||||
anchors.fill: parent
|
||||
color: DefaultStyle.grey_0
|
||||
radius: Math.round(16 * DefaultStyle.dp)
|
||||
}
|
||||
MultiEffect {
|
||||
source: popupBackground
|
||||
anchors.fill: popupBackground
|
||||
shadowEnabled: true
|
||||
shadowBlur: 0.1
|
||||
shadowColor: DefaultStyle.grey_1000
|
||||
shadowOpacity: 0.4
|
||||
}
|
||||
}
|
||||
contentItem: ColumnLayout {
|
||||
IconLabelButton {
|
||||
//: "Supprimer"
|
||||
text: qsTr("chat_message_delete")
|
||||
icon.source: AppIcons.trashCan
|
||||
spacing: Math.round(10 * DefaultStyle.dp)
|
||||
Layout.fillWidth: true
|
||||
onClicked: {
|
||||
mainItem.messageDeletionRequested()
|
||||
optionsMenu.close()
|
||||
}
|
||||
style: ButtonStyle.noBackgroundRed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
background: Item {
|
||||
anchors.fill: parent
|
||||
Rectangle {
|
||||
id: popupBackground
|
||||
anchors.fill: parent
|
||||
color: DefaultStyle.grey_0
|
||||
color: mainItem.backgroundColor
|
||||
radius: Math.round(16 * DefaultStyle.dp)
|
||||
}
|
||||
MultiEffect {
|
||||
source: popupBackground
|
||||
anchors.fill: popupBackground
|
||||
shadowEnabled: true
|
||||
shadowBlur: 0.1
|
||||
shadowColor: DefaultStyle.grey_1000
|
||||
shadowOpacity: 0.4
|
||||
Rectangle {
|
||||
visible: mainItem.isFirstMessage && mainItem.isRemoteMessage
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
width: Math.round(parent.width / 4)
|
||||
height: Math.round(parent.height / 4)
|
||||
color: mainItem.backgroundColor
|
||||
}
|
||||
Rectangle {
|
||||
visible: mainItem.isFirstMessage && !mainItem.isRemoteMessage
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
width: Math.round(parent.width / 4)
|
||||
height: Math.round(parent.height / 4)
|
||||
color: mainItem.backgroundColor
|
||||
}
|
||||
}
|
||||
contentItem: ColumnLayout {
|
||||
IconLabelButton {
|
||||
//: "Supprimer"
|
||||
text: qsTr("chat_message_delete")
|
||||
icon.source: AppIcons.trashCan
|
||||
spacing: Math.round(10 * DefaultStyle.dp)
|
||||
id: contentLayout
|
||||
Image {
|
||||
visible: mainItem.imgUrl != undefined
|
||||
id: contentimage
|
||||
}
|
||||
Text {
|
||||
visible: modelData.core.text != undefined
|
||||
text: modelData.core.text
|
||||
Layout.fillWidth: true
|
||||
onClicked: {
|
||||
mainItem.messageDeletionRequested()
|
||||
optionsMenu.close()
|
||||
color: DefaultStyle.main2_700
|
||||
font {
|
||||
pixelSize: Typography.p1.pixelSize
|
||||
weight: Typography.p1.weight
|
||||
}
|
||||
style: ButtonStyle.noBackgroundRed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
background: Item {
|
||||
anchors.fill: parent
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: mainItem.backgroundColor
|
||||
radius: Math.round(16 * DefaultStyle.dp)
|
||||
}
|
||||
Rectangle {
|
||||
visible: mainItem.isFirstMessage && mainItem.isRemoteMessage
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
width: Math.round(parent.width / 4)
|
||||
height: Math.round(parent.height / 4)
|
||||
color: mainItem.backgroundColor
|
||||
}
|
||||
Rectangle {
|
||||
visible: mainItem.isFirstMessage && !mainItem.isRemoteMessage
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
width: Math.round(parent.width / 4)
|
||||
height: Math.round(parent.height / 4)
|
||||
color: mainItem.backgroundColor
|
||||
}
|
||||
}
|
||||
contentItem: ColumnLayout {
|
||||
id: contentLayout
|
||||
Image {
|
||||
visible: mainItem.imgUrl != undefined
|
||||
id: contentimage
|
||||
}
|
||||
Text {
|
||||
visible: mainItem.contentText != undefined
|
||||
text: mainItem.contentText
|
||||
Layout.fillWidth: true
|
||||
color: DefaultStyle.main2_700
|
||||
font {
|
||||
pixelSize: Typography.p1.pixelSize
|
||||
weight: Typography.p1.weight
|
||||
}
|
||||
}
|
||||
Text {
|
||||
Layout.alignment: Qt.AlignRight
|
||||
text: UtilsCpp.formatDate(modelData.core.timestamp, true, false)
|
||||
color: DefaultStyle.main2_500main
|
||||
font {
|
||||
pixelSize: Typography.p3.pixelSize
|
||||
weight: Typography.p3.weight
|
||||
Text {
|
||||
Layout.alignment: Qt.AlignRight
|
||||
text: UtilsCpp.formatDate(modelData.core.timestamp, true, false)
|
||||
color: DefaultStyle.main2_500main
|
||||
font {
|
||||
pixelSize: Typography.p3.pixelSize
|
||||
weight: Typography.p3.weight
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,13 +11,15 @@ import "qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js" as Utils
|
|||
ListView {
|
||||
id: mainItem
|
||||
property ChatGui chat
|
||||
spacing: Math.round(20 * DefaultStyle.dp)
|
||||
property color backgroundColor
|
||||
spacing: Math.round(4 * DefaultStyle.dp)
|
||||
|
||||
Component.onCompleted: positionViewAtEnd()
|
||||
|
||||
onCountChanged: positionViewAtEnd();
|
||||
onCountChanged: positionViewAtEnd()
|
||||
|
||||
model: ChatMessageProxy {
|
||||
id: chatMessageProxy
|
||||
chatGui: mainItem.chat
|
||||
}
|
||||
|
||||
|
|
@ -26,17 +28,49 @@ ListView {
|
|||
}
|
||||
|
||||
delegate: ChatMessage {
|
||||
id: chatMessage
|
||||
width: Math.min(implicitWidth, Math.round(mainItem.width * (3/4)))
|
||||
chatMessage: modelData
|
||||
property real maxWidth: Math.round(mainItem.width * (3/4))
|
||||
// height: childrenRect.height
|
||||
// width: childrenRect.width
|
||||
property var previousIndex: index - 1
|
||||
property var previousFromAddress: chatMessageProxy.getChatMessageAtIndex(index-1)?.core.fromAddress
|
||||
backgroundColor: isRemoteMessage ? DefaultStyle.main2_100 : DefaultStyle.main1_100
|
||||
contentText: modelData.core.text
|
||||
isFirstMessage: true
|
||||
isRemoteMessage: modelData.core.isRemoteMessage
|
||||
isFirstMessage: !previousFromAddress || previousFromAddress !== modelData.core.fromAddress
|
||||
anchors.right: !isRemoteMessage && parent
|
||||
? parent.right
|
||||
: undefined
|
||||
|
||||
onMessageDeletionRequested: modelData.core.lDelete()
|
||||
}
|
||||
}
|
||||
|
||||
footerPositioning: ListView.OverlayFooter
|
||||
footer: Control.Control {
|
||||
visible: composeLayout.composingName !== ""
|
||||
width: mainItem.width
|
||||
z: mainItem.z + 2
|
||||
topPadding: Math.round(5 * DefaultStyle.dp)
|
||||
bottomPadding: Math.round(5 * DefaultStyle.dp)
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
color: mainItem.panelColor
|
||||
}
|
||||
contentItem: RowLayout {
|
||||
id: composeLayout
|
||||
property string composingName: mainItem.chat.core.composingName
|
||||
Avatar {
|
||||
Layout.preferredWidth: Math.round(20 * DefaultStyle.dp)
|
||||
Layout.preferredHeight: Math.round(20 * DefaultStyle.dp)
|
||||
_address: mainItem.chat.core.composingAddress
|
||||
}
|
||||
Text {
|
||||
Layout.fillWidth: true
|
||||
font {
|
||||
pixelSize: Typography.p3.pixelSize
|
||||
weight: Typography.p3.weight
|
||||
}
|
||||
//: %1 is writing…
|
||||
text: qsTr("%1 est en train d'écrire…").arg(composeLayout.composingName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -84,7 +84,6 @@ Loader{
|
|||
Connections{
|
||||
target: mainItem
|
||||
onHaveAvatarChanged: {
|
||||
console.log("have avatar changed", mainItem.haveAvatar, mainItem._address)
|
||||
stackView.replace(mainItem.haveAvatar ? avatar : initials, StackView.Immediate)}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,8 +34,7 @@ FocusScope {
|
|||
property real itemsRightMargin: Math.round(39 * DefaultStyle.dp)
|
||||
|
||||
property var displayName: searchResultItem.core.fullName
|
||||
property string initial: displayName ? displayName[0].toLocaleLowerCase(
|
||||
ConstantsCpp.DefaultLocale) : ''
|
||||
property string initial: displayName ? displayName[0].toLocaleLowerCase(ConstantsCpp.DefaultLocale) : ''
|
||||
|
||||
signal clicked(var mouse)
|
||||
signal contactDeletionRequested(FriendGui contact)
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ RowLayout {
|
|||
ChatMessagesListView {
|
||||
id: chatMessagesListView
|
||||
height: contentHeight
|
||||
backgroundColor: panelColor
|
||||
width: parent.width - anchors.leftMargin - anchors.rightMargin
|
||||
chat: mainItem.chat
|
||||
anchors.top: parent.top
|
||||
|
|
@ -88,7 +89,6 @@ RowLayout {
|
|||
anchors.bottom: messageSender.top
|
||||
anchors.leftMargin: Math.round(18 * DefaultStyle.dp)
|
||||
anchors.rightMargin: Math.round(18 * DefaultStyle.dp)
|
||||
anchors.bottomMargin: Math.round(18 * DefaultStyle.dp)
|
||||
Control.ScrollBar.vertical: scrollbar
|
||||
},
|
||||
ScrollBar {
|
||||
|
|
@ -106,13 +106,22 @@ RowLayout {
|
|||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: 79 * DefaultStyle.dp
|
||||
leftPadding: Math.round(15 * DefaultStyle.dp)
|
||||
rightPadding: Math.round(15 * DefaultStyle.dp)
|
||||
topPadding: Math.round(16 * DefaultStyle.dp)
|
||||
topPadding: Math.round(24 * DefaultStyle.dp)
|
||||
bottomPadding: Math.round(16 * DefaultStyle.dp)
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
color: DefaultStyle.grey_100
|
||||
MediumButton {
|
||||
id: expandButton
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: Math.round(4 * DefaultStyle.dp)
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
style: ButtonStyle.noBackgroundOrange
|
||||
icon.source: checked ? AppIcons.downArrow : AppIcons.upArrow
|
||||
checkable: true
|
||||
}
|
||||
}
|
||||
contentItem: RowLayout {
|
||||
spacing: Math.round(20 * DefaultStyle.dp)
|
||||
|
|
@ -135,19 +144,62 @@ RowLayout {
|
|||
}
|
||||
Control.Control {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: Math.round(48 * DefaultStyle.dp)
|
||||
leftPadding: Math.round(15 * DefaultStyle.dp)
|
||||
rightPadding: Math.round(15 * DefaultStyle.dp)
|
||||
topPadding: Math.round(16 * DefaultStyle.dp)
|
||||
bottomPadding: Math.round(16 * DefaultStyle.dp)
|
||||
background: Rectangle {
|
||||
id: inputBackground
|
||||
anchors.fill: parent
|
||||
radius: Math.round(30 * DefaultStyle.dp)
|
||||
radius: Math.round(35 * DefaultStyle.dp)
|
||||
color: DefaultStyle.grey_0
|
||||
}
|
||||
contentItem: RowLayout {
|
||||
TextArea {
|
||||
id: sendingTextArea
|
||||
Flickable {
|
||||
id: sendingAreaFlickable
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.preferredWidth: parent.width - stackButton.width
|
||||
Layout.preferredHeight: Math.min(Math.round(60 * DefaultStyle.dp), contentHeight)
|
||||
Binding {
|
||||
target: sendingAreaFlickable
|
||||
when: expandButton.checked
|
||||
property: "Layout.preferredHeight"
|
||||
value: Math.round(250 * DefaultStyle.dp)
|
||||
restoreMode: Binding.RestoreBindingOrValue
|
||||
}
|
||||
Layout.fillHeight: true
|
||||
contentHeight: sendingTextArea.contentHeight
|
||||
contentWidth: width
|
||||
|
||||
function ensureVisible(r) {
|
||||
if (contentX >= r.x)
|
||||
contentX = r.x;
|
||||
else if (contentX+width <= r.x+r.width)
|
||||
contentX = r.x+r.width-width;
|
||||
if (contentY >= r.y)
|
||||
contentY = r.y;
|
||||
else if (contentY+height <= r.y+r.height)
|
||||
contentY = r.y+r.height-height;
|
||||
}
|
||||
|
||||
TextArea {
|
||||
id: sendingTextArea
|
||||
width: parent.width
|
||||
height: sendingAreaFlickable.height
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
//: Say something… : placeholder text for sending message text area
|
||||
placeholderText: qsTr("Dites quelque chose…")
|
||||
placeholderTextColor: DefaultStyle.main2_400
|
||||
onCursorRectangleChanged: sendingAreaFlickable.ensureVisible(cursorRectangle)
|
||||
property string previousText
|
||||
Component.onCompleted: previousText = text
|
||||
onTextChanged: {
|
||||
if (previousText === "" && text !== "") {
|
||||
mainItem.chat.core.lCompose()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
StackLayout {
|
||||
id: stackButton
|
||||
|
|
@ -163,7 +215,8 @@ RowLayout {
|
|||
style: ButtonStyle.noBackgroundOrange
|
||||
icon.source: AppIcons.paperPlaneRight
|
||||
onClicked: {
|
||||
console.log("TODO : send message")
|
||||
mainItem.chat.core.lSendTextMessage(sendingTextArea.text)
|
||||
sendingTextArea.clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ AbstractMainPage {
|
|||
property string remoteAddress
|
||||
onRemoteAddressChanged: console.log("ChatPage : remote address changed :", remoteAddress)
|
||||
property var remoteChatObj: UtilsCpp.getChatForAddress(remoteAddress)
|
||||
property ChatGui remoteChat: remoteChatObj ? remoteChatObj.value : null
|
||||
property ChatGui remoteChat: remoteChatObj && remoteChatObj.value ? remoteChatObj.value : null
|
||||
onRemoteChatChanged: if (remoteChat) selectedChatGui = remoteChat
|
||||
|
||||
onSelectedChatGuiChanged: {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,13 @@ QtObject {
|
|||
weight: Math.min(Math.round(800 * DefaultStyle.dp), 1000)
|
||||
})
|
||||
|
||||
// Text/P4 - Xsmall paragraph text
|
||||
property font p4: Qt.font( {
|
||||
family: DefaultStyle.defaultFont,
|
||||
pixelSize: Math.round(10 * DefaultStyle.dp),
|
||||
weight: Math.min(Math.round(300 * DefaultStyle.dp), 1000)
|
||||
})
|
||||
|
||||
// Text/P3 - Reduced paragraph text
|
||||
property font p3: Qt.font( {
|
||||
family: DefaultStyle.defaultFont,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue