mirror of
https://git.jami.net/savoirfairelinux/jami-client-qt.git
synced 2025-04-21 21:52:03 +02:00
share message: add share feature
A share feature have been requested to share to contacts pictures or text received from other contacts you can access it by hovering the message you want to share Gitlab: #1830 Change-Id: I2555433417867371161f927e9fc78bb47fec68d3
This commit is contained in:
parent
59f3aa7c44
commit
31bd0392da
7 changed files with 515 additions and 17 deletions
11
resources/icons/share_black_24dp.svg
Normal file
11
resources/icons/share_black_24dp.svg
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||||
|
<path d="M17.1,15.7c-0.8,0-1.5,0.3-2.1,0.8l-5.3-3.3C9.9,12.8,10,12.4,10,12c0-0.4-0.1-0.8-0.3-1.2l5.3-3.3c0.6,0.5,1.3,0.8,2.1,0.8
|
||||||
|
c1.7,0,3.1-1.4,3.1-3.1S18.9,2,17.1,2C15.4,2,14,3.4,14,5.1c0,0.4,0.1,0.8,0.3,1.2L8.9,9.6C8.3,9.1,7.6,8.9,6.9,8.9
|
||||||
|
c-1.7,0-3.1,1.4-3.1,3.1s1.4,3.1,3.1,3.1c0.8,0,1.5-0.3,2.1-0.8l5.3,3.3C14.1,18,14,18.4,14,18.9c0,1.7,1.4,3.1,3.1,3.1
|
||||||
|
c1.7,0,3.1-1.4,3.1-3.1S18.9,15.7,17.1,15.7z M17.1,20.6c-1,0-1.8-0.8-1.8-1.8s0.8-1.8,1.8-1.8c1,0,1.8,0.8,1.8,1.8
|
||||||
|
S18.1,20.6,17.1,20.6z M17.1,3.4c1,0,1.8,0.8,1.8,1.8s-0.8,1.8-1.8,1.8c-1,0-1.8-0.8-1.8-1.8S16.2,3.4,17.1,3.4z M6.9,13.8
|
||||||
|
c-1,0-1.8-0.8-1.8-1.8s0.8-1.8,1.8-1.8S8.6,11,8.6,12S7.8,13.8,6.9,13.8z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1,019 B |
|
@ -278,7 +278,7 @@ Control {
|
||||||
|
|
||||||
anchors.right: isOutgoing ? bubble.left : undefined
|
anchors.right: isOutgoing ? bubble.left : undefined
|
||||||
anchors.left: !isOutgoing ? bubble.right : undefined
|
anchors.left: !isOutgoing ? bubble.right : undefined
|
||||||
width: JamiTheme.emojiPushButtonSize * 2
|
width: JamiTheme.emojiPushButtonSize * 4
|
||||||
height: JamiTheme.emojiPushButtonSize
|
height: JamiTheme.emojiPushButtonSize
|
||||||
anchors.verticalCenter: bubble.verticalCenter
|
anchors.verticalCenter: bubble.verticalCenter
|
||||||
|
|
||||||
|
@ -299,24 +299,24 @@ Control {
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.right: isOutgoing ? optionButtonItem.right : undefined
|
anchors.right: isOutgoing ? optionButtonItem.right : undefined
|
||||||
anchors.left: !isOutgoing ? optionButtonItem.left : undefined
|
anchors.left: !isOutgoing ? optionButtonItem.left : undefined
|
||||||
visible: CurrentAccount.type !== Profile.Type.SIP && root.type !== Interaction.Type.CALL && Body !== "" && (bubbleArea.bubbleHovered || hovered || reply.hovered || bgHandler.hovered)
|
visible: CurrentAccount.type !== Profile.Type.SIP && root.type !== Interaction.Type.CALL && Body !== "" && (bubbleArea.bubbleHovered || hovered || reply.hovered || share.hovered || bgHandler.hovered)
|
||||||
source: JamiResources.more_vert_24dp_svg
|
source: JamiResources.more_vert_24dp_svg
|
||||||
width: optionButtonItem.width / 2
|
width: optionButtonItem.width / 4
|
||||||
height: optionButtonItem.height
|
height: optionButtonItem.height
|
||||||
circled: false
|
circled: false
|
||||||
property bool isOpen: false
|
property bool isOpen: false
|
||||||
property var obj: undefined
|
property var obj: undefined
|
||||||
|
|
||||||
function bind() {
|
function setBindings() {
|
||||||
more.isOpen = false;
|
more.isOpen = false;
|
||||||
visible = Qt.binding(() => CurrentAccount.type !== Profile.Type.SIP && root.type !== Interaction.Type.CALL && Body !== "" && (bubbleArea.bubbleHovered || hovered || reply.hovered || bgHandler.hovered));
|
visible = Qt.binding(() => CurrentAccount.type !== Profile.Type.SIP && root.type !== Interaction.Type.CALL && Body !== "" && (bubbleArea.bubbleHovered || hovered || reply.hovered || share.hovered || bgHandler.hovered));
|
||||||
imageColor = Qt.binding(() => hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor);
|
imageColor = Qt.binding(() => hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor);
|
||||||
normalColor = Qt.binding(() => JamiTheme.primaryBackgroundColor);
|
normalColor = Qt.binding(() => JamiTheme.primaryBackgroundColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (more.isOpen) {
|
if (more.isOpen) {
|
||||||
more.bind();
|
more.setBindings();
|
||||||
obj.close();
|
obj.close();
|
||||||
} else {
|
} else {
|
||||||
var component = Qt.createComponent("qrc:/commoncomponents/ShowMoreMenu.qml");
|
var component = Qt.createComponent("qrc:/commoncomponents/ShowMoreMenu.qml");
|
||||||
|
@ -332,7 +332,7 @@ Control {
|
||||||
});
|
});
|
||||||
obj.open();
|
obj.open();
|
||||||
more.isOpen = true;
|
more.isOpen = true;
|
||||||
visible = true;
|
visible = true; // the button stay visible as long the popup is open even if it's not hovered
|
||||||
imageColor = JamiTheme.chatViewFooterImgHoverColor;
|
imageColor = JamiTheme.chatViewFooterImgHoverColor;
|
||||||
normalColor = JamiTheme.hoveredButtonColor;
|
normalColor = JamiTheme.hoveredButtonColor;
|
||||||
}
|
}
|
||||||
|
@ -348,19 +348,75 @@ Control {
|
||||||
normalColor: JamiTheme.primaryBackgroundColor
|
normalColor: JamiTheme.primaryBackgroundColor
|
||||||
toolTipText: JamiStrings.reply
|
toolTipText: JamiStrings.reply
|
||||||
source: JamiResources.reply_black_24dp_svg
|
source: JamiResources.reply_black_24dp_svg
|
||||||
width: optionButtonItem.width / 2
|
width: optionButtonItem.width / 4
|
||||||
height: optionButtonItem.height
|
height: optionButtonItem.height
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.rightMargin: 5
|
anchors.rightMargin: 5
|
||||||
anchors.right: isOutgoing ? more.left : undefined
|
anchors.right: isOutgoing ? more.left : undefined
|
||||||
anchors.left: !isOutgoing ? more.right : undefined
|
anchors.left: !isOutgoing ? more.right : undefined
|
||||||
visible: CurrentAccount.type !== Profile.Type.SIP && root.type !== Interaction.Type.CALL && Body !== "" && (bubbleArea.bubbleHovered || hovered || more.hovered || bgHandler.hovered)
|
visible: CurrentAccount.type !== Profile.Type.SIP && root.type !== Interaction.Type.CALL && Body !== "" && (bubbleArea.bubbleHovered || hovered || more.hovered || share.hovered || bgHandler.hovered)
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
MessagesAdapter.editId = "";
|
MessagesAdapter.editId = "";
|
||||||
MessagesAdapter.replyToId = Id;
|
MessagesAdapter.replyToId = Id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PushButton {
|
||||||
|
id: share
|
||||||
|
objectName: "share"
|
||||||
|
|
||||||
|
circled: false
|
||||||
|
imageColor: hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor
|
||||||
|
normalColor: JamiTheme.primaryBackgroundColor
|
||||||
|
toolTipText: JamiStrings.share
|
||||||
|
source: JamiResources.share_black_24dp_svg
|
||||||
|
|
||||||
|
width: optionButtonItem.width / 4
|
||||||
|
height: optionButtonItem.height
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.rightMargin: 5
|
||||||
|
anchors.right: isOutgoing ? reply.left : undefined
|
||||||
|
anchors.left: !isOutgoing ? reply.right : undefined
|
||||||
|
visible: CurrentAccount.type !== Profile.Type.SIP && root.type !== Interaction.Type.CALL && Body !== "" && (bubbleArea.bubbleHovered || hovered || reply.hovered || more.hovered || bgHandler.hovered)
|
||||||
|
property bool isOpen: false
|
||||||
|
property var obj: undefined
|
||||||
|
|
||||||
|
function setBindings() { // when the popup is closed, setBindings is called to reset the icon's visual settings
|
||||||
|
share.isOpen = false;
|
||||||
|
visible = Qt.binding(() => CurrentAccount.type !== Profile.Type.SIP && root.type !== Interaction.Type.CALL && Body !== "" && (bubbleArea.bubbleHovered || hovered || reply.hovered || more.hovered || bgHandler.hovered));
|
||||||
|
imageColor = Qt.binding(() => hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor);
|
||||||
|
normalColor = Qt.binding(() => JamiTheme.primaryBackgroundColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (share.isOpen) {
|
||||||
|
share.setBindings();
|
||||||
|
obj.close();
|
||||||
|
} else {
|
||||||
|
if (root.type === 2 || root.type === 5) {
|
||||||
|
// 2=TEXT and 5=DATA_TRANSFER (any kind of file) defined in interaction.h
|
||||||
|
var component = Qt.createComponent("qrc:/commoncomponents/ShareMessageMenu.qml");
|
||||||
|
obj = component.createObject(share, {
|
||||||
|
"isOutgoing": isOutgoing,
|
||||||
|
"msgId": Id,
|
||||||
|
"msgBody": Body,
|
||||||
|
"type": root.type,
|
||||||
|
"transferName": TransferName,
|
||||||
|
"msgBubble": bubble,
|
||||||
|
"listView": listView,
|
||||||
|
"author": UtilsAdapter.getBestNameForUri(CurrentAccount.id, Author),
|
||||||
|
"formattedTime": formattedTime
|
||||||
|
});
|
||||||
|
obj.open();
|
||||||
|
share.isOpen = true;
|
||||||
|
visible = true; // the PushButton stay visible as long the popup is open even if it's not hovered
|
||||||
|
imageColor = JamiTheme.chatViewFooterImgHoverColor;
|
||||||
|
normalColor = JamiTheme.hoveredButtonColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageBubble {
|
MessageBubble {
|
||||||
|
@ -382,11 +438,7 @@ Control {
|
||||||
property bool bubbleHovered
|
property bool bubbleHovered
|
||||||
property string imgSource
|
property string imgSource
|
||||||
|
|
||||||
width: (root.type === Interaction.Type.TEXT || isDeleted ?
|
width: (root.type === Interaction.Type.TEXT || isDeleted ? root.textContentWidth + (IsEmojiOnly || root.bigMsg ? 0 : root.timeWidth + root.editedWidth) : innerContent.childrenRect.width)
|
||||||
root.textContentWidth + (IsEmojiOnly || root.bigMsg ?
|
|
||||||
0
|
|
||||||
: root.timeWidth + root.editedWidth)
|
|
||||||
: innerContent.childrenRect.width)
|
|
||||||
height: innerContent.childrenRect.height + (visible ? root.extraHeight : 0) + (root.bigMsg ? 15 : 0)
|
height: innerContent.childrenRect.height + (visible ? root.extraHeight : 0) + (root.bigMsg ? 15 : 0)
|
||||||
|
|
||||||
HoverHandler {
|
HoverHandler {
|
||||||
|
@ -470,6 +522,11 @@ Control {
|
||||||
MessagesAdapter.openUrl(root.hoveredLink);
|
MessagesAdapter.openUrl(root.hoveredLink);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onDoubleClicked: {
|
||||||
|
MessagesAdapter.editId = "";
|
||||||
|
MessagesAdapter.replyToId = Id;
|
||||||
|
}
|
||||||
property bool bubbleHovered: containsMouse || textHovered
|
property bool bubbleHovered: containsMouse || textHovered
|
||||||
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||||
}
|
}
|
||||||
|
|
264
src/app/commoncomponents/ShareMessageMenu.qml
Normal file
264
src/app/commoncomponents/ShareMessageMenu.qml
Normal file
|
@ -0,0 +1,264 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024 Savoir-faire Linux Inc.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Qt5Compat.GraphicalEffects
|
||||||
|
import net.jami.Constants 1.1
|
||||||
|
import net.jami.Models 1.1
|
||||||
|
import net.jami.Adapters 1.1
|
||||||
|
import SortFilterProxyModel 0.2
|
||||||
|
import "contextmenu"
|
||||||
|
import "../commoncomponents"
|
||||||
|
import "../mainview/components"
|
||||||
|
|
||||||
|
BaseContextMenu {
|
||||||
|
id: mainMenu
|
||||||
|
|
||||||
|
height: 330 + Math.min(messageInput.height, textareaMaxHeight)
|
||||||
|
width: 400
|
||||||
|
|
||||||
|
required property string msgId
|
||||||
|
required property string msgBody
|
||||||
|
required property bool isOutgoing
|
||||||
|
required property int type
|
||||||
|
required property string transferName
|
||||||
|
required property Item msgBubble
|
||||||
|
required property ListView listView
|
||||||
|
required property string author
|
||||||
|
required property string formattedTime
|
||||||
|
|
||||||
|
property var selectedUids: []
|
||||||
|
property string shareToId: msgId
|
||||||
|
property string fileLink: msgBody
|
||||||
|
property int textareaMaxHeight: 350
|
||||||
|
function xPosition(width) {
|
||||||
|
// Use the width at function scope to retrigger property evaluation.
|
||||||
|
const listViewWidth = listView.width;
|
||||||
|
const parentX = parent.x;
|
||||||
|
if (isOutgoing) {
|
||||||
|
return parentX - width - 20;
|
||||||
|
} else {
|
||||||
|
return parentX + 20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
x: xPosition(width)
|
||||||
|
y: parent.y
|
||||||
|
|
||||||
|
function xPositionProvider(width) {
|
||||||
|
// Use the width at function scope to retrigger property evaluation.
|
||||||
|
const listViewWidth = listView.width;
|
||||||
|
if (isOutgoing) {
|
||||||
|
return -5 - width;
|
||||||
|
} else {
|
||||||
|
const rightMargin = listViewWidth - (msgBubble.x + width);
|
||||||
|
return width > rightMargin + 35 ? -5 - width : 35;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function yPositionProvider(height) {
|
||||||
|
const topOffset = msgBubble.mapToItem(listView, 0, 0).y;
|
||||||
|
const listViewHeight = listView.height;
|
||||||
|
const bottomMargin = listViewHeight - height - topOffset;
|
||||||
|
if (bottomMargin < 0 || (topOffset < 0 && topOffset + height > 0)) {
|
||||||
|
return 30 - height;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SortFilterProxyModel {
|
||||||
|
id: shareConvProxyModel
|
||||||
|
|
||||||
|
sourceModel: ConversationsAdapter.convListProxyModel
|
||||||
|
filterCaseSensitivity: Qt.CaseInsensitive
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: header
|
||||||
|
|
||||||
|
width: parent.width
|
||||||
|
height: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: sendButton
|
||||||
|
|
||||||
|
height: JamiTheme.chatViewFooterButtonSize
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: 10
|
||||||
|
anchors.topMargin: 10
|
||||||
|
anchors.top: header.bottom
|
||||||
|
color: JamiTheme.transparentColor
|
||||||
|
|
||||||
|
PushButton {
|
||||||
|
id: shareMessageButton
|
||||||
|
|
||||||
|
height: JamiTheme.chatViewFooterButtonSize
|
||||||
|
width: scale * JamiTheme.chatViewFooterButtonSize
|
||||||
|
anchors.right: parent.right
|
||||||
|
|
||||||
|
visible: true
|
||||||
|
|
||||||
|
radius: JamiTheme.chatViewFooterButtonRadius
|
||||||
|
preferredSize: JamiTheme.chatViewFooterButtonIconSize - 6
|
||||||
|
imageContainerWidth: 25
|
||||||
|
imageContainerHeight: 25
|
||||||
|
|
||||||
|
toolTipText: JamiStrings.share
|
||||||
|
|
||||||
|
mirror: UtilsAdapter.isRTL
|
||||||
|
|
||||||
|
source: JamiResources.send_black_24dp_svg
|
||||||
|
|
||||||
|
hoverEnabled: enabled
|
||||||
|
normalColor: enabled ? JamiTheme.chatViewFooterSendButtonColor : JamiTheme.chatViewFooterSendButtonDisableColor
|
||||||
|
imageColor: enabled ? JamiTheme.chatViewFooterSendButtonImgColor : JamiTheme.chatViewFooterSendButtonImgColorDisable
|
||||||
|
hoveredColor: JamiTheme.buttonTintedBlueHovered
|
||||||
|
pressedColor: hoveredColor
|
||||||
|
|
||||||
|
opacity: 1
|
||||||
|
scale: opacity
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
var selectedContacts = mainMenu.selectedUids;
|
||||||
|
var hasText = messageInput.text && selectedContacts.length > 0;
|
||||||
|
function sendMessageOrFile(uid) {
|
||||||
|
if (Type === 2) {
|
||||||
|
// 2=TEXT and 5=DATA_TRANSFER (any kind of file) defined in interaction.h
|
||||||
|
MessagesAdapter.sendMessageToUid(msgBody, uid);
|
||||||
|
} else {
|
||||||
|
MessagesAdapter.sendFileToUid(fileLink, uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var i = 0; i < selectedContacts.length; i++) {
|
||||||
|
var uid = selectedContacts[i];
|
||||||
|
sendMessageOrFile(uid);
|
||||||
|
if (hasText) {
|
||||||
|
MessagesAdapter.sendMessageToUid(messageInput.text, uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
messageInput.text = "";
|
||||||
|
mainMenu.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: searchConv
|
||||||
|
|
||||||
|
height: 300
|
||||||
|
width: parent.width
|
||||||
|
anchors.top: header.bottom
|
||||||
|
anchors.topMargin: 10
|
||||||
|
|
||||||
|
property int type: ContactList.CONVERSATION
|
||||||
|
|
||||||
|
color: JamiTheme.transparentColor
|
||||||
|
ColumnLayout {
|
||||||
|
id: contactPickerPopupRectColumnLayout
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
Searchbar {
|
||||||
|
id: contactPickerContactSearchBar
|
||||||
|
|
||||||
|
width: parent.width - 20 - JamiTheme.chatViewFooterButtonSize
|
||||||
|
anchors.leftMargin: 10
|
||||||
|
Layout.preferredHeight: 35
|
||||||
|
placeHolderText: "Share to..."
|
||||||
|
onSearchBarTextChanged: function (text) {
|
||||||
|
shareConvProxyModel.filterRole = shareConvProxyModel.roleForName("Title");
|
||||||
|
shareConvProxyModel.filterPattern = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JamiListView {
|
||||||
|
id: contactPickerListView
|
||||||
|
|
||||||
|
Layout.alignment: Qt.AlignCenter
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: 255
|
||||||
|
Layout.bottomMargin: JamiTheme.preferredMarginSize
|
||||||
|
Layout.topMargin: 5
|
||||||
|
|
||||||
|
model: shareConvProxyModel
|
||||||
|
|
||||||
|
delegate: ConversationPickerItemDelegate {
|
||||||
|
id: conversationDelegate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Flickable {
|
||||||
|
id: messageInputContainer
|
||||||
|
|
||||||
|
height: Math.min(contentHeight, mainMenu.textareaMaxHeight)
|
||||||
|
width: parent.width - 20
|
||||||
|
contentHeight: messageInput.height
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: 10
|
||||||
|
anchors.rightMargin: 10
|
||||||
|
anchors.topMargin: 10
|
||||||
|
anchors.top: searchConv.bottom
|
||||||
|
|
||||||
|
flickableDirection: Flickable.VerticalFlick
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
ScrollBar.vertical: JamiScrollBar {
|
||||||
|
policy: ScrollBar.AsNeeded
|
||||||
|
}
|
||||||
|
|
||||||
|
onContentHeightChanged: {
|
||||||
|
if (contentHeight > height) {
|
||||||
|
contentY = contentHeight - height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TextArea {
|
||||||
|
id: messageInput
|
||||||
|
|
||||||
|
height: contentHeight + 12
|
||||||
|
width: parent.width
|
||||||
|
placeholderText: "Add a comment"
|
||||||
|
placeholderTextColor: JamiTheme.messageBarPlaceholderTextColor
|
||||||
|
font.pointSize: JamiTheme.textFontSize + 2
|
||||||
|
color: JamiTheme.textColor
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
color: JamiTheme.transparentColor
|
||||||
|
radius: 5
|
||||||
|
border.color: JamiTheme.chatViewFooterRectangleBorderColor
|
||||||
|
border.width: 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// destroy() and setBindings() are needed to unselect the share icon from SBSMessageBase
|
||||||
|
|
||||||
|
onAboutToHide: {
|
||||||
|
mainMenu.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onDestruction: {
|
||||||
|
parent.setBindings();
|
||||||
|
}
|
||||||
|
}
|
|
@ -198,11 +198,13 @@ BaseContextMenu {
|
||||||
root.loadMenuItems(menuItems);
|
root.loadMenuItems(menuItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// destroy() and setBindings() are needed to unselect the share icon from SBSMessageBase
|
||||||
|
|
||||||
onAboutToHide: {
|
onAboutToHide: {
|
||||||
root.destroy();
|
root.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onDestruction: {
|
Component.onDestruction: {
|
||||||
parent.bind();
|
parent.setBindings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
138
src/app/mainview/components/ConversationPickerItemDelegate.qml
Normal file
138
src/app/mainview/components/ConversationPickerItemDelegate.qml
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024 Savoir-faire Linux Inc.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Qt5Compat.GraphicalEffects
|
||||||
|
import net.jami.Adapters 1.1
|
||||||
|
import net.jami.Constants 1.1
|
||||||
|
import net.jami.Enums 1.1
|
||||||
|
import net.jami.Models 1.1
|
||||||
|
import "../../commoncomponents"
|
||||||
|
|
||||||
|
ItemDelegate {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
width: ListView.view.width
|
||||||
|
height: JamiTheme.smartListItemHeight
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.leftMargin: 15
|
||||||
|
anchors.rightMargin: 15
|
||||||
|
spacing: 10
|
||||||
|
|
||||||
|
ConversationAvatar {
|
||||||
|
id: avatar
|
||||||
|
objectName: "smartlistItemDelegateAvatar"
|
||||||
|
|
||||||
|
imageId: UID
|
||||||
|
presenceStatus: Presence
|
||||||
|
showPresenceIndicator: Presence !== undefined ? Presence : false
|
||||||
|
|
||||||
|
Layout.preferredWidth: JamiTheme.smartListAvatarSize
|
||||||
|
Layout.preferredHeight: JamiTheme.smartListAvatarSize
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: overlayHighlighted
|
||||||
|
visible: highlighted
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
color: Qt.rgba(0, 0, 0, 0.5)
|
||||||
|
radius: JamiTheme.smartListAvatarSize / 2
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: highlightedImage
|
||||||
|
|
||||||
|
width: JamiTheme.smartListAvatarSize / 2
|
||||||
|
height: JamiTheme.smartListAvatarSize / 2
|
||||||
|
anchors.centerIn: parent
|
||||||
|
|
||||||
|
layer {
|
||||||
|
enabled: true
|
||||||
|
effect: ColorOverlay {
|
||||||
|
color: "white"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
source: JamiResources.check_black_24dp_svg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
// best name
|
||||||
|
Text {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.minimumHeight: 20
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
horizontalAlignment: Text.AlignLeft
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
elide: Text.ElideMiddle
|
||||||
|
text: Title === undefined ? "" : Title
|
||||||
|
textFormat: TextEdit.PlainText
|
||||||
|
font.pointSize: JamiTheme.mediumFontSize
|
||||||
|
font.weight: UnreadMessagesCount ? Font.Bold : Font.Normal
|
||||||
|
color: JamiTheme.textColor
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.minimumHeight: 20
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
text: JamiStrings.blocked
|
||||||
|
textFormat: TextEdit.PlainText
|
||||||
|
visible: IsBanned
|
||||||
|
font.pointSize: JamiTheme.mediumFontSize
|
||||||
|
font.weight: Font.Bold
|
||||||
|
color: JamiTheme.textColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Accessible.role: Accessible.Button
|
||||||
|
Accessible.name: Title === undefined ? "" : Title
|
||||||
|
}
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
color: {
|
||||||
|
if (root.pressed || root.highlighted)
|
||||||
|
return JamiTheme.smartListSelectedColor;
|
||||||
|
else if (root.hovered)
|
||||||
|
return JamiTheme.smartListHoveredColor;
|
||||||
|
else
|
||||||
|
return "transparent";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
highlighted: {
|
||||||
|
return mainMenu.selectedUids.includes(UID);
|
||||||
|
}
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
const currentSelectedUids = mainMenu.selectedUids;
|
||||||
|
if (currentSelectedUids.includes(UID)) {
|
||||||
|
mainMenu.selectedUids = currentSelectedUids.filter(uid => uid !== UID);
|
||||||
|
} else {
|
||||||
|
mainMenu.selectedUids = currentSelectedUids.concat(UID);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
|
@ -165,6 +165,16 @@ MessagesAdapter::sendMessage(const QString& message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MessagesAdapter::sendMessageToUid(const QString& message, const QString& convUid)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
lrcInstance_->getCurrentConversationModel()->sendMessage(convUid, message, replyToId_);
|
||||||
|
} catch (...) {
|
||||||
|
qDebug() << "Exception during sendMessage:" << message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MessagesAdapter::editMessage(const QString& convId, const QString& newBody, const QString& messageId)
|
MessagesAdapter::editMessage(const QString& convId, const QString& newBody, const QString& messageId)
|
||||||
{
|
{
|
||||||
|
@ -221,6 +231,21 @@ MessagesAdapter::sendFile(const QString& message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MessagesAdapter::sendFileToUid(const QString& message, const QString& convUid)
|
||||||
|
{
|
||||||
|
QFileInfo fi(message);
|
||||||
|
QString fileName = fi.fileName();
|
||||||
|
try {
|
||||||
|
lrcInstance_->getCurrentConversationModel()->sendFile(convUid,
|
||||||
|
message,
|
||||||
|
fileName,
|
||||||
|
replyToId_);
|
||||||
|
} catch (...) {
|
||||||
|
qDebug() << "Exception during sendFile";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MessagesAdapter::joinCall(const QString& uri,
|
MessagesAdapter::joinCall(const QString& uri,
|
||||||
const QString& deviceId,
|
const QString& deviceId,
|
||||||
|
@ -312,8 +337,7 @@ MessagesAdapter::onPaste()
|
||||||
QString path = QDir::temp().filePath(fileName);
|
QString path = QDir::temp().filePath(fileName);
|
||||||
|
|
||||||
if (!pixmap.save(path, "PNG")) {
|
if (!pixmap.save(path, "PNG")) {
|
||||||
qDebug().noquote() << "Errors during QPixmap save"
|
qDebug().noquote() << "Errors during QPixmap save" << "\n";
|
||||||
<< "\n";
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -126,6 +126,7 @@ public:
|
||||||
Q_INVOKABLE void unbanContact(int index);
|
Q_INVOKABLE void unbanContact(int index);
|
||||||
Q_INVOKABLE void unbanConversation(const QString& convUid);
|
Q_INVOKABLE void unbanConversation(const QString& convUid);
|
||||||
Q_INVOKABLE void sendMessage(const QString& message);
|
Q_INVOKABLE void sendMessage(const QString& message);
|
||||||
|
Q_INVOKABLE void sendMessageToUid(const QString& message, const QString& convUid);
|
||||||
Q_INVOKABLE void editMessage(const QString& convId,
|
Q_INVOKABLE void editMessage(const QString& convId,
|
||||||
const QString& newBody,
|
const QString& newBody,
|
||||||
const QString& messageId = "");
|
const QString& messageId = "");
|
||||||
|
@ -136,6 +137,7 @@ public:
|
||||||
const QString& emoji,
|
const QString& emoji,
|
||||||
const QString& messageId);
|
const QString& messageId);
|
||||||
Q_INVOKABLE void sendFile(const QString& message);
|
Q_INVOKABLE void sendFile(const QString& message);
|
||||||
|
Q_INVOKABLE void sendFileToUid(const QString& message, const QString& convUid);
|
||||||
Q_INVOKABLE void acceptFile(const QString& arg);
|
Q_INVOKABLE void acceptFile(const QString& arg);
|
||||||
Q_INVOKABLE void cancelFile(const QString& arg);
|
Q_INVOKABLE void cancelFile(const QString& arg);
|
||||||
Q_INVOKABLE void openUrl(const QString& url);
|
Q_INVOKABLE void openUrl(const QString& url);
|
||||||
|
|
Loading…
Add table
Reference in a new issue