mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-01-17 11:28:07 +00:00
copy message text to clipboard + improve chat message and sending area ui
This commit is contained in:
parent
ecd9373df9
commit
73b83771be
9 changed files with 197 additions and 113 deletions
|
|
@ -97,10 +97,12 @@ void ChatList::setSelf(QSharedPointer<ChatList> me) {
|
|||
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";
|
||||
if (found == list.end()) {
|
||||
auto model = createChatCore(chatRoom);
|
||||
mModelConnection->invokeToCore([this, model]() { add(model); });
|
||||
mModelConnection->invokeToCore([this, model]() {
|
||||
add(model);
|
||||
emit chatAdded();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ signals:
|
|||
void lUpdate();
|
||||
void filterChanged(QString filter);
|
||||
void chatRemoved(ChatGui *chat);
|
||||
void chatAdded();
|
||||
|
||||
private:
|
||||
QString mFilter;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ DEFINE_ABSTRACT_OBJECT(ChatProxy)
|
|||
ChatProxy::ChatProxy(QObject *parent) : LimitProxy(parent) {
|
||||
mList = ChatList::create();
|
||||
setSourceModel(mList.get());
|
||||
setDynamicSortFilter(true);
|
||||
}
|
||||
|
||||
ChatProxy::~ChatProxy() {
|
||||
|
|
@ -43,8 +44,10 @@ void ChatProxy::setSourceModel(QAbstractItemModel *model) {
|
|||
connect(this, &ChatProxy::filterTextChanged, newChatList,
|
||||
[this, newChatList] { emit newChatList->filterChanged(getFilterText()); });
|
||||
connect(newChatList, &ChatList::chatRemoved, this, &ChatProxy::chatRemoved);
|
||||
connect(newChatList, &ChatList::chatAdded, this, [this] { invalidate(); });
|
||||
}
|
||||
setSourceModels(new SortFilterList(model));
|
||||
auto firstList = new SortFilterList(model, Qt::AscendingOrder);
|
||||
setSourceModels(firstList);
|
||||
sort(0);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,9 +13,11 @@ Button {
|
|||
radius: Math.round(5 * DefaultStyle.dp)
|
||||
shadowEnabled: mainItem.activeFocus || hovered
|
||||
style: ButtonStyle.hoveredBackground
|
||||
property bool inverseLayout: false
|
||||
|
||||
contentItem: RowLayout {
|
||||
spacing: Math.round(5 * DefaultStyle.dp)
|
||||
layoutDirection: mainItem.inverseLayout ? Qt.RightToLeft: Qt.LeftToRight
|
||||
EffectImage {
|
||||
imageSource: mainItem.icon.source
|
||||
imageWidth: mainItem.icon.width
|
||||
|
|
@ -33,6 +35,7 @@ Button {
|
|||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
Layout.preferredWidth: textMetrics.advanceWidth
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.WrapAnywhere
|
||||
text: mainItem.text
|
||||
maximumLineCount: 1
|
||||
|
|
|
|||
|
|
@ -8,137 +8,177 @@ 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
|
||||
|
||||
|
||||
RowLayout {
|
||||
Control.Control {
|
||||
id: mainItem
|
||||
property color backgroundColor
|
||||
property bool isFirstMessage
|
||||
|
||||
property string imgUrl
|
||||
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
|
||||
hoverEnabled: true
|
||||
|
||||
signal messageDeletionRequested()
|
||||
|
||||
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()
|
||||
}
|
||||
background: Item {
|
||||
anchors.fill: parent
|
||||
Text {
|
||||
id: fromNameText
|
||||
visible: mainItem.isFromChatGroup && mainItem.isRemoteMessage && mainItem.isFirstMessage
|
||||
anchors.top: parent.top
|
||||
maximumLineCount: 1
|
||||
width: implicitWidth
|
||||
x: chatBubble.x
|
||||
text: mainItem.chatMessage.core.fromName
|
||||
color: DefaultStyle.main2_500main
|
||||
font {
|
||||
pixelSize: Typography.p4.pixelSize
|
||||
weight: Typography.p4.weight
|
||||
}
|
||||
}
|
||||
Popup {
|
||||
id: optionsMenu
|
||||
}
|
||||
|
||||
contentItem: RowLayout {
|
||||
spacing: 0
|
||||
layoutDirection: mainItem.isRemoteMessage ? Qt.LeftToRight : Qt.RightToLeft
|
||||
|
||||
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 {
|
||||
id: chatBubble
|
||||
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)
|
||||
spacing: Math.round(2 * DefaultStyle.dp)
|
||||
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) => {
|
||||
if (mouse.button === Qt.RightButton) {
|
||||
optionsMenu.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
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: modelData.core.text != undefined
|
||||
text: modelData.core.text
|
||||
Layout.fillWidth: true
|
||||
color: DefaultStyle.main2_700
|
||||
font {
|
||||
pixelSize: Typography.p1.pixelSize
|
||||
weight: Typography.p1.weight
|
||||
RowLayout {
|
||||
id: actionsLayout
|
||||
visible: mainItem.hovered || optionsMenu.hovered || optionsMenu.popup.opened || emojiButton.hovered
|
||||
Layout.leftMargin: Math.round(8 * DefaultStyle.dp)
|
||||
Layout.rightMargin: Math.round(8 * DefaultStyle.dp)
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
// Layout.fillWidth: true
|
||||
spacing: Math.round(7 * DefaultStyle.dp)
|
||||
layoutDirection: mainItem.isRemoteMessage ? Qt.LeftToRight : Qt.RightToLeft
|
||||
PopupButton {
|
||||
id: optionsMenu
|
||||
popup.padding: 0
|
||||
popup.contentItem: ColumnLayout {
|
||||
spacing: 0
|
||||
IconLabelButton {
|
||||
inverseLayout: true
|
||||
//: "Copy"
|
||||
text: qsTr("chat_message_copy")
|
||||
icon.source: AppIcons.copy
|
||||
// spacing: Math.round(10 * DefaultStyle.dp)
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 45 * DefaultStyle.dp
|
||||
onClicked: {
|
||||
var success = UtilsCpp.copyToClipboard(modelData.core.text)
|
||||
//: Copied
|
||||
if (success) UtilsCpp.showInformationPopup(qsTr("chat_message_copied_to_clipboard_title"),
|
||||
//: "in clipboard"
|
||||
qsTr("chat_message_copied_to_clipboard_toast"))
|
||||
}
|
||||
}
|
||||
IconLabelButton {
|
||||
inverseLayout: true
|
||||
//: "Delete"
|
||||
text: qsTr("chat_message_delete")
|
||||
icon.source: AppIcons.trashCan
|
||||
// spacing: Math.round(10 * DefaultStyle.dp)
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 45 * DefaultStyle.dp
|
||||
onClicked: {
|
||||
mainItem.messageDeletionRequested()
|
||||
optionsMenu.close()
|
||||
}
|
||||
style: ButtonStyle.hoveredBackgroundRed
|
||||
}
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
BigButton {
|
||||
id: emojiButton
|
||||
style: ButtonStyle.noBackground
|
||||
icon.source: AppIcons.smiley
|
||||
}
|
||||
}
|
||||
Item{Layout.fillWidth: true}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,13 +14,41 @@ ListView {
|
|||
property color backgroundColor
|
||||
spacing: Math.round(4 * DefaultStyle.dp)
|
||||
|
||||
Component.onCompleted: positionViewAtEnd()
|
||||
// Component.onCompleted: positionViewAtIndex(chatMessageProxy.findFirstUnreadIndex(), ListView.Visible)
|
||||
|
||||
onCountChanged: positionViewAtEnd()
|
||||
onAtYEndChanged: if (atYEnd) chat.core.lMarkAsRead();
|
||||
|
||||
onChatChanged: if (visible) {
|
||||
var index = chatMessageProxy.findFirstUnreadIndex()
|
||||
console.log("visible, first unread at index", index)
|
||||
mainItem.positionViewAtIndex(index, ListView.Visible)
|
||||
}
|
||||
|
||||
RoundButton {
|
||||
icon.source: AppIcons.downArrow
|
||||
// Layout.preferredWidth: 40 * DefaultStyle.dp
|
||||
// Layout.preferredHeight: 40 * DefaultStyle.dp
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
anchors.bottomMargin: Math.round(18 * DefaultStyle.dp)
|
||||
anchors.rightMargin: Math.round(18 * DefaultStyle.dp)
|
||||
onClicked: {
|
||||
var index = chatMessageProxy.findFirstUnreadIndex()
|
||||
console.log("clicked, first unread at index", index)
|
||||
mainItem.positionViewAtIndex(index, ListView.Visible)
|
||||
// var chatMessage = chatMessageProxy.getChatMessageAtIndex(index)
|
||||
// if (chatMessage && !chatMessage.core.isRead) chatMessage.core.lMarkAsRead()
|
||||
}
|
||||
}
|
||||
|
||||
model: ChatMessageProxy {
|
||||
id: chatMessageProxy
|
||||
chatGui: mainItem.chat
|
||||
onCountChanged: {
|
||||
var indexToSelect = mainItem.currentIndex
|
||||
mainItem.currentIndex = -1
|
||||
mainItem.currentIndex = indexToSelect
|
||||
}
|
||||
}
|
||||
|
||||
header: Item {
|
||||
|
|
@ -31,7 +59,7 @@ ListView {
|
|||
chatMessage: modelData
|
||||
property real maxWidth: Math.round(mainItem.width * (3/4))
|
||||
// height: childrenRect.height
|
||||
// width: childrenRect.width
|
||||
width: mainItem.width
|
||||
property var previousIndex: index - 1
|
||||
property var previousFromAddress: chatMessageProxy.getChatMessageAtIndex(index-1)?.core.fromAddress
|
||||
backgroundColor: isRemoteMessage ? DefaultStyle.main2_100 : DefaultStyle.main1_100
|
||||
|
|
@ -52,7 +80,7 @@ ListView {
|
|||
bottomPadding: Math.round(5 * DefaultStyle.dp)
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
color: mainItem.panelColor
|
||||
color: mainItem.backgroundColor
|
||||
}
|
||||
contentItem: RowLayout {
|
||||
id: composeLayout
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ RowLayout {
|
|||
ChatMessagesListView {
|
||||
id: chatMessagesListView
|
||||
height: contentHeight
|
||||
backgroundColor: panelColor
|
||||
backgroundColor: splitPanel.panelColor
|
||||
width: parent.width - anchors.leftMargin - anchors.rightMargin
|
||||
chat: mainItem.chat
|
||||
anchors.top: parent.top
|
||||
|
|
@ -146,8 +146,8 @@ RowLayout {
|
|||
Layout.fillWidth: true
|
||||
leftPadding: Math.round(15 * DefaultStyle.dp)
|
||||
rightPadding: Math.round(15 * DefaultStyle.dp)
|
||||
topPadding: Math.round(16 * DefaultStyle.dp)
|
||||
bottomPadding: Math.round(16 * DefaultStyle.dp)
|
||||
topPadding: Math.round(15 * DefaultStyle.dp)
|
||||
bottomPadding: Math.round(15 * DefaultStyle.dp)
|
||||
background: Rectangle {
|
||||
id: inputBackground
|
||||
anchors.fill: parent
|
||||
|
|
@ -188,9 +188,15 @@ RowLayout {
|
|||
height: sendingAreaFlickable.height
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
wrapMode: TextEdit.WordWrap
|
||||
//: Say something… : placeholder text for sending message text area
|
||||
placeholderText: qsTr("Dites quelque chose…")
|
||||
placeholderTextColor: DefaultStyle.main2_400
|
||||
color: DefaultStyle.main2_700
|
||||
font {
|
||||
pixelSize: Typography.p1.pixelSize
|
||||
weight: Typography.p1.weight
|
||||
}
|
||||
onCursorRectangleChanged: sendingAreaFlickable.ensureVisible(cursorRectangle)
|
||||
property string previousText
|
||||
Component.onCompleted: previousText = text
|
||||
|
|
|
|||
|
|
@ -684,8 +684,8 @@ AbstractMainPage {
|
|||
KeyNavigation.up: deletePopup
|
||||
KeyNavigation.down: joinButton
|
||||
onClicked: {
|
||||
UtilsCpp.copyToClipboard(mainItem.selectedConference.core.uri)
|
||||
UtilsCpp.showInformationPopup(qsTr("saved"),
|
||||
var success = UtilsCpp.copyToClipboard(mainItem.selectedConference.core.uri)
|
||||
if (success) UtilsCpp.showInformationPopup(qsTr("saved"),
|
||||
//: "Adresse de la réunion copiée"
|
||||
qsTr("meeting_address_copied_to_clipboard_toast"))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,7 +113,8 @@
|
|||
color: {
|
||||
normal: Linphone.DefaultStyle.grey_500,
|
||||
hovered: Linphone.DefaultStyle.grey_600,
|
||||
pressed: Linphone.DefaultStyle.main2_400
|
||||
pressed: Linphone.DefaultStyle.main2_400,
|
||||
hovered: Linphone.DefaultStyle.main2_400
|
||||
},
|
||||
text: {
|
||||
normal: Linphone.DefaultStyle.grey_0,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue