mirror of
https://git.jami.net/savoirfairelinux/jami-client-qt.git
synced 2025-07-26 02:15:33 +02:00
chatview: refactor msg options popup positioning
+ load the popup dynamically + calculate the position using the delegate's attached ListView geometry Gitlab: #979 Change-Id: I9d3a8a31b4aba2f195c4d6453e9dca88e99685ae
This commit is contained in:
parent
42a46fe165
commit
4612d5318b
8 changed files with 112 additions and 127 deletions
|
@ -26,6 +26,8 @@ import net.jami.Models 1.1
|
||||||
ListView {
|
ListView {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
property alias verticalScrollBar: verticalScrollBar
|
||||||
|
|
||||||
layer.mipmap: false
|
layer.mipmap: false
|
||||||
clip: true
|
clip: true
|
||||||
maximumFlickVelocity: 1024
|
maximumFlickVelocity: 1024
|
||||||
|
@ -36,11 +38,6 @@ ListView {
|
||||||
attachedFlickableMoving: root.moving
|
attachedFlickableMoving: root.moving
|
||||||
}
|
}
|
||||||
|
|
||||||
property bool isScrolling: verticalScrollBar.active
|
|
||||||
onIsScrollingChanged: {
|
|
||||||
JamiQmlUtils.isChatviewScrolling = isScrolling
|
|
||||||
}
|
|
||||||
|
|
||||||
Keys.onUpPressed: verticalScrollBar.decrease()
|
Keys.onUpPressed: verticalScrollBar.decrease()
|
||||||
Keys.onDownPressed: verticalScrollBar.increase()
|
Keys.onDownPressed: verticalScrollBar.increase()
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
import Qt5Compat.GraphicalEffects
|
import Qt5Compat.GraphicalEffects
|
||||||
|
@ -32,22 +33,79 @@ Popup {
|
||||||
padding: 0
|
padding: 0
|
||||||
background.visible: false
|
background.visible: false
|
||||||
|
|
||||||
property string msgId
|
required property string msgId
|
||||||
property string msg
|
required property string msgBody
|
||||||
property var emojiReplied
|
required property var emojiReplied
|
||||||
property bool out
|
required property bool isOutgoing
|
||||||
property int type
|
required property int type
|
||||||
|
required property string transferName
|
||||||
|
required property Item msgBubble
|
||||||
|
required property ListView listView
|
||||||
|
|
||||||
property string transferId: msgId
|
property string transferId: msgId
|
||||||
property string location: Body
|
property string location: msgBody
|
||||||
property string transferName
|
|
||||||
property bool closeWithoutAnimation: false
|
property bool closeWithoutAnimation: false
|
||||||
|
property var emojiPicker
|
||||||
|
|
||||||
|
function xPositionProvider(width) {
|
||||||
|
// Use the width at function scope to retrigger property evaluation.
|
||||||
|
const listViewWidth = listView.width
|
||||||
|
if (isOutgoing) {
|
||||||
|
const leftMargin = msgBubble.mapToItem(listView, 0, 0).x
|
||||||
|
return width > leftMargin ? -leftMargin : -width
|
||||||
|
} else {
|
||||||
|
const rightMargin = listViewWidth - (msgBubble.x + msgBubble.width)
|
||||||
|
return width > rightMargin ? msgBubble.width - width : msgBubble.width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function yPositionProvider(height) {
|
||||||
|
const topOffset = msgBubble.mapToItem(listView, 0, 0).y
|
||||||
|
if (topOffset < 0) return -topOffset
|
||||||
|
const bottomOffset = topOffset + height - listView.height
|
||||||
|
if (bottomOffset > 0) return -bottomOffset
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
x: xPositionProvider(width)
|
||||||
|
y: yPositionProvider(height)
|
||||||
|
|
||||||
signal addMoreEmoji
|
signal addMoreEmoji
|
||||||
|
onAddMoreEmoji: {
|
||||||
onOpened: {
|
JamiQmlUtils.updateMessageBarButtonsPoints()
|
||||||
root.closeWithoutAnimation = false
|
openEmojiPicker()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openEmojiPicker() {
|
||||||
|
var component = WITH_WEBENGINE ?
|
||||||
|
Qt.createComponent("qrc:/webengine/emojipicker/EmojiPicker.qml") :
|
||||||
|
Qt.createComponent("qrc:/nowebengine/EmojiPicker.qml")
|
||||||
|
emojiPicker = component.createObject(root.parent, { listView: listView })
|
||||||
|
emojiPicker.emojiIsPicked.connect(function(content) {
|
||||||
|
if (emojiReplied.includes(content)) {
|
||||||
|
MessagesAdapter.removeEmojiReaction(CurrentConversation.id, content, msgId)
|
||||||
|
} else {
|
||||||
|
MessagesAdapter.addEmojiReaction(CurrentConversation.id, content, msgId)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (emojiPicker !== null) {
|
||||||
|
root.opacity = 0
|
||||||
|
emojiPicker.closed.connect(() => close())
|
||||||
|
emojiPicker.x = xPositionProvider(JamiTheme.emojiPickerWidth)
|
||||||
|
emojiPicker.y = yPositionProvider(JamiTheme.emojiPickerHeight)
|
||||||
|
emojiPicker.open()
|
||||||
|
} else {
|
||||||
|
console.log("Error creating emojiPicker from message options popup");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the picker when listView vertical properties change.
|
||||||
|
property real listViewHeight: listView.height
|
||||||
|
onListViewHeightChanged: close()
|
||||||
|
property bool isScrolling: listView.verticalScrollBar.active
|
||||||
|
onIsScrollingChanged: close()
|
||||||
|
|
||||||
|
onOpened: root.closeWithoutAnimation = false
|
||||||
|
onClosed: if (emojiPicker) emojiPicker.closeEmojiPicker()
|
||||||
|
|
||||||
function getModel() {
|
function getModel() {
|
||||||
var model = ["👍", "👎", "😂"]
|
var model = ["👍", "👎", "😂"]
|
||||||
var cur = []
|
var cur = []
|
||||||
|
@ -132,7 +190,7 @@ Popup {
|
||||||
onClicked: {
|
onClicked: {
|
||||||
root.closeWithoutAnimation = true
|
root.closeWithoutAnimation = true
|
||||||
root.addMoreEmoji()
|
root.addMoreEmoji()
|
||||||
close()
|
//close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,7 +210,7 @@ Popup {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.margins: 5
|
Layout.margins: 5
|
||||||
onClicked: {
|
onClicked: {
|
||||||
UtilsAdapter.setClipboardText(msg)
|
UtilsAdapter.setClipboardText(msgBody)
|
||||||
close()
|
close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -184,7 +242,7 @@ Popup {
|
||||||
MessageOptionButton {
|
MessageOptionButton {
|
||||||
id: buttonEdit
|
id: buttonEdit
|
||||||
|
|
||||||
visible: root.out && type === Interaction.Type.TEXT
|
visible: root.isOutgoing && type === Interaction.Type.TEXT
|
||||||
textButton: JamiStrings.editMessage
|
textButton: JamiStrings.editMessage
|
||||||
iconSource: JamiResources.edit_svg
|
iconSource: JamiResources.edit_svg
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
@ -198,7 +256,7 @@ Popup {
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageOptionButton {
|
MessageOptionButton {
|
||||||
visible: root.out && type === Interaction.Type.TEXT
|
visible: root.isOutgoing && type === Interaction.Type.TEXT
|
||||||
textButton: JamiStrings.deleteMessage
|
textButton: JamiStrings.deleteMessage
|
||||||
iconSource: JamiResources.delete_svg
|
iconSource: JamiResources.delete_svg
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
|
@ -55,9 +55,15 @@ Control {
|
||||||
readonly property real hPadding: JamiTheme.sbsMessageBasePreferredPadding
|
readonly property real hPadding: JamiTheme.sbsMessageBasePreferredPadding
|
||||||
property bool textHovered: false
|
property bool textHovered: false
|
||||||
property alias replyAnimation: selectAnimation
|
property alias replyAnimation: selectAnimation
|
||||||
width: ListView.view ? ListView.view.width : 0
|
width: listView.width
|
||||||
height: mainColumnLayout.implicitHeight
|
height: mainColumnLayout.implicitHeight
|
||||||
|
|
||||||
|
// If the ListView attached properties are not available,
|
||||||
|
// then the root delegate is likely a Loader.
|
||||||
|
readonly property ListView listView: ListView.view ?
|
||||||
|
ListView.view :
|
||||||
|
parent.ListView.view
|
||||||
|
|
||||||
rightPadding: hPadding
|
rightPadding: hPadding
|
||||||
leftPadding: hPadding
|
leftPadding: hPadding
|
||||||
|
|
||||||
|
@ -184,9 +190,18 @@ Control {
|
||||||
height: optionButtonItem.height
|
height: optionButtonItem.height
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
messageOptionPopup.open()
|
var component = Qt.createComponent("qrc:/commoncomponents/MessageOptionsPopup.qml")
|
||||||
messageOptionPopup.x = messageOptionPopup.setXposition(messageOptionPopup.width)
|
var obj = component.createObject(bubble, {
|
||||||
messageOptionPopup.y = messageOptionPopup.setYposition(messageOptionPopup.height)
|
"emojiReplied": Qt.binding(() => emojiReaction.emojiTexts),
|
||||||
|
"isOutgoing": isOutgoing,
|
||||||
|
"msgId": Id,
|
||||||
|
"msgBody": Body,
|
||||||
|
"type": Type,
|
||||||
|
"transferName": TransferName,
|
||||||
|
"msgBubble": bubble,
|
||||||
|
"listView": listView
|
||||||
|
})
|
||||||
|
obj.open()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,103 +229,6 @@ Control {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatviewMessageOptions {
|
|
||||||
id: messageOptionPopup
|
|
||||||
|
|
||||||
emojiReplied: emojiReaction.emojiTexts
|
|
||||||
out: isOutgoing
|
|
||||||
msgId: Id
|
|
||||||
msg: Body
|
|
||||||
type: Type
|
|
||||||
transferName: TransferName
|
|
||||||
visible: false
|
|
||||||
|
|
||||||
property bool isScrolling: JamiQmlUtils.isChatviewScrolling
|
|
||||||
property real rootWidth: root.width
|
|
||||||
property var emojiPicker
|
|
||||||
|
|
||||||
onIsScrollingChanged: {
|
|
||||||
messageOptionPopup.close()
|
|
||||||
if (messageOptionPopup.emojiPicker)
|
|
||||||
messageOptionPopup.emojiPicker.closeEmojiPicker()
|
|
||||||
}
|
|
||||||
|
|
||||||
onAddMoreEmoji: {
|
|
||||||
JamiQmlUtils.updateMessageBarButtonsPoints()
|
|
||||||
openEmojiPicker()
|
|
||||||
}
|
|
||||||
|
|
||||||
onRootWidthChanged: {
|
|
||||||
if (emojiPicker)
|
|
||||||
emojiPicker.x = setXposition(JamiTheme.emojiPickerWidth)
|
|
||||||
messageOptionPopup.x = setXposition(width)
|
|
||||||
messageOptionPopup.y = setYposition(height)
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: messageOptionPopup.emojiPicker ? messageOptionPopup.emojiPicker : null
|
|
||||||
function onEmojiIsPicked(content) {
|
|
||||||
if (messageOptionPopup.emojiReplied.includes(content))
|
|
||||||
MessagesAdapter.removeEmojiReaction(CurrentConversation.id,content,messageOptionPopup.msgId)
|
|
||||||
else
|
|
||||||
MessagesAdapter.addEmojiReaction(CurrentConversation.id,content,messageOptionPopup.msgId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function openEmojiPicker() {
|
|
||||||
var component = WITH_WEBENGINE
|
|
||||||
? Qt.createComponent("qrc:/webengine/emojipicker/EmojiPicker.qml")
|
|
||||||
: Qt.createComponent("qrc:/nowebengine/EmojiPicker.qml")
|
|
||||||
messageOptionPopup.emojiPicker = component.createObject(msgRowlayout,
|
|
||||||
{
|
|
||||||
x: setXposition(JamiTheme.emojiPickerWidth),
|
|
||||||
y: setYposition(JamiTheme.emojiPickerHeight)
|
|
||||||
});
|
|
||||||
if (messageOptionPopup.emojiPicker !== null) {
|
|
||||||
messageOptionPopup.emojiPicker.open()
|
|
||||||
} else {
|
|
||||||
console.log("Error creating emojiPicker in SBSMessageBase");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setXposition(width) {
|
|
||||||
|
|
||||||
var distBorders = root.width - bubble.width - width
|
|
||||||
if (isOutgoing) {
|
|
||||||
if (distBorders > 0)
|
|
||||||
x = bubble.x - width
|
|
||||||
else
|
|
||||||
x = bubble.x
|
|
||||||
} else {
|
|
||||||
if (distBorders > 0)
|
|
||||||
x = bubble.x + bubble.width
|
|
||||||
else
|
|
||||||
x = bubble.x + bubble.width - width
|
|
||||||
}
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
function setYposition(height) {
|
|
||||||
var bottomOffset = 0
|
|
||||||
if (JamiQmlUtils.messageBarButtonsRowObj) {
|
|
||||||
bottomOffset = JamiQmlUtils.messageBarButtonsRowObj.height
|
|
||||||
}
|
|
||||||
var mappedCoord = bubble.mapToItem(appWindow.contentItem, 0, 0)
|
|
||||||
var distBottomScreen = appWindow.height - mappedCoord.y - height - bottomOffset
|
|
||||||
if (distBottomScreen < 0) {
|
|
||||||
return distBottomScreen
|
|
||||||
}
|
|
||||||
var topOffset = 0
|
|
||||||
if (JamiQmlUtils.messagingHeaderRectRowLayout) {
|
|
||||||
topOffset = JamiQmlUtils.messagingHeaderRectRowLayout.height
|
|
||||||
}
|
|
||||||
var distTopScreen = mappedCoord.y - topOffset
|
|
||||||
if (distTopScreen < 0)
|
|
||||||
return -distTopScreen
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageBubble {
|
MessageBubble {
|
||||||
id: bubble
|
id: bubble
|
||||||
|
|
||||||
|
@ -321,7 +239,8 @@ Control {
|
||||||
function getBaseColor() {
|
function getBaseColor() {
|
||||||
var baseColor = isOutgoing ? JamiTheme.messageOutBgColor
|
var baseColor = isOutgoing ? JamiTheme.messageOutBgColor
|
||||||
: CurrentConversation.isCoreDialog ?
|
: CurrentConversation.isCoreDialog ?
|
||||||
JamiTheme.messageInBgColor : Qt.lighter(CurrentConversation.color, 1.5)
|
JamiTheme.messageInBgColor :
|
||||||
|
Qt.lighter(CurrentConversation.color, 1.5)
|
||||||
if (Id === MessagesAdapter.replyToId || Id === MessagesAdapter.editId) {
|
if (Id === MessagesAdapter.replyToId || Id === MessagesAdapter.editId) {
|
||||||
// If we are replying to or editing the message
|
// If we are replying to or editing the message
|
||||||
return Qt.darker(baseColor, 1.5)
|
return Qt.darker(baseColor, 1.5)
|
||||||
|
|
|
@ -38,10 +38,6 @@ Item {
|
||||||
Object.assign(JamiQmlUtils.accountCreationInputParaObject, inputPara)
|
Object.assign(JamiQmlUtils.accountCreationInputParaObject, inputPara)
|
||||||
return accountCreationInputParaObject
|
return accountCreationInputParaObject
|
||||||
}
|
}
|
||||||
//to know if the chatview is being scrolled
|
|
||||||
property bool isChatviewScrolling
|
|
||||||
//chatviewHeader
|
|
||||||
property var messagingHeaderRectRowLayout
|
|
||||||
|
|
||||||
// MessageBar buttons in mainview points
|
// MessageBar buttons in mainview points
|
||||||
property var mainViewRectObj
|
property var mainViewRectObj
|
||||||
|
|
|
@ -150,7 +150,11 @@ Rectangle {
|
||||||
? Qt.createComponent("qrc:/webengine/emojipicker/EmojiPicker.qml")
|
? Qt.createComponent("qrc:/webengine/emojipicker/EmojiPicker.qml")
|
||||||
: Qt.createComponent("qrc:/nowebengine/EmojiPicker.qml")
|
: Qt.createComponent("qrc:/nowebengine/EmojiPicker.qml")
|
||||||
messageBar.emojiPicker =
|
messageBar.emojiPicker =
|
||||||
component.createObject(messageBar, {x: setXposition(), y: setYposition()});
|
component.createObject(messageBar, {
|
||||||
|
x: setXposition(),
|
||||||
|
y: setYposition(),
|
||||||
|
listView: null
|
||||||
|
});
|
||||||
if (messageBar.emojiPicker === null) {
|
if (messageBar.emojiPicker === null) {
|
||||||
console.log("Error creating emojiPicker in chatViewFooter");
|
console.log("Error creating emojiPicker in chatViewFooter");
|
||||||
}
|
}
|
||||||
|
|
|
@ -260,7 +260,6 @@ Rectangle {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Component.onCompleted: JamiQmlUtils.messagingHeaderRectRowLayout = messagingHeaderRectRowLayout
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomBorder {
|
CustomBorder {
|
||||||
|
|
|
@ -21,6 +21,8 @@ import QtQuick
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
required property ListView listView
|
||||||
|
|
||||||
signal emojiIsPicked(string content)
|
signal emojiIsPicked(string content)
|
||||||
function openEmojiPicker() {}
|
function openEmojiPicker() {}
|
||||||
function closeEmojiPicker() {}
|
function closeEmojiPicker() {}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import Qt5Compat.GraphicalEffects
|
||||||
import QtWebEngine
|
import QtWebEngine
|
||||||
import QtWebChannel
|
import QtWebChannel
|
||||||
|
|
||||||
|
import net.jami.Models 1.1
|
||||||
import net.jami.Constants 1.1
|
import net.jami.Constants 1.1
|
||||||
import net.jami.Adapters 1.1
|
import net.jami.Adapters 1.1
|
||||||
|
|
||||||
|
@ -31,8 +32,17 @@ import "../"
|
||||||
Popup {
|
Popup {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
required property ListView listView
|
||||||
|
|
||||||
signal emojiIsPicked(string content)
|
signal emojiIsPicked(string content)
|
||||||
|
|
||||||
|
// Close the picker when attached to a listView that receives height/scroll
|
||||||
|
// property changes.
|
||||||
|
property real listViewHeight: listView ? listView.height : 0
|
||||||
|
onListViewHeightChanged: close()
|
||||||
|
property bool isScrolling: listView ? listView.verticalScrollBar.active : false
|
||||||
|
onIsScrollingChanged: close()
|
||||||
|
|
||||||
function openEmojiPicker() {
|
function openEmojiPicker() {
|
||||||
root.open()
|
root.open()
|
||||||
emojiPickerWebView.runJavaScript(
|
emojiPickerWebView.runJavaScript(
|
||||||
|
|
Loading…
Add table
Reference in a new issue