Skip to content
Snippets Groups Projects
Commit 4612d531 authored by Andreas Traczyk's avatar Andreas Traczyk
Browse files

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
parent 42a46fe1
Branches
Tags
No related merge requests found
......@@ -26,6 +26,8 @@ import net.jami.Models 1.1
ListView {
id: root
property alias verticalScrollBar: verticalScrollBar
layer.mipmap: false
clip: true
maximumFlickVelocity: 1024
......@@ -36,11 +38,6 @@ ListView {
attachedFlickableMoving: root.moving
}
property bool isScrolling: verticalScrollBar.active
onIsScrollingChanged: {
JamiQmlUtils.isChatviewScrolling = isScrolling
}
Keys.onUpPressed: verticalScrollBar.decrease()
Keys.onDownPressed: verticalScrollBar.increase()
}
......@@ -15,6 +15,7 @@
* 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 Qt5Compat.GraphicalEffects
......@@ -32,21 +33,78 @@ Popup {
padding: 0
background.visible: false
property string msgId
property string msg
property var emojiReplied
property bool out
property int type
required property string msgId
required property string msgBody
required property var emojiReplied
required property bool isOutgoing
required property int type
required property string transferName
required property Item msgBubble
required property ListView listView
property string transferId: msgId
property string location: Body
property string transferName
property string location: msgBody
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
onAddMoreEmoji: {
JamiQmlUtils.updateMessageBarButtonsPoints()
openEmojiPicker()
}
onOpened: {
root.closeWithoutAnimation = false
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() {
var model = ["👍", "👎", "😂"]
......@@ -132,7 +190,7 @@ Popup {
onClicked: {
root.closeWithoutAnimation = true
root.addMoreEmoji()
close()
//close()
}
}
}
......@@ -152,7 +210,7 @@ Popup {
Layout.fillWidth: true
Layout.margins: 5
onClicked: {
UtilsAdapter.setClipboardText(msg)
UtilsAdapter.setClipboardText(msgBody)
close()
}
}
......@@ -184,7 +242,7 @@ Popup {
MessageOptionButton {
id: buttonEdit
visible: root.out && type === Interaction.Type.TEXT
visible: root.isOutgoing && type === Interaction.Type.TEXT
textButton: JamiStrings.editMessage
iconSource: JamiResources.edit_svg
Layout.fillWidth: true
......@@ -198,7 +256,7 @@ Popup {
}
MessageOptionButton {
visible: root.out && type === Interaction.Type.TEXT
visible: root.isOutgoing && type === Interaction.Type.TEXT
textButton: JamiStrings.deleteMessage
iconSource: JamiResources.delete_svg
Layout.fillWidth: true
......
......@@ -55,9 +55,15 @@ Control {
readonly property real hPadding: JamiTheme.sbsMessageBasePreferredPadding
property bool textHovered: false
property alias replyAnimation: selectAnimation
width: ListView.view ? ListView.view.width : 0
width: listView.width
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
leftPadding: hPadding
......@@ -184,9 +190,18 @@ Control {
height: optionButtonItem.height
onClicked: {
messageOptionPopup.open()
messageOptionPopup.x = messageOptionPopup.setXposition(messageOptionPopup.width)
messageOptionPopup.y = messageOptionPopup.setYposition(messageOptionPopup.height)
var component = Qt.createComponent("qrc:/commoncomponents/MessageOptionsPopup.qml")
var obj = component.createObject(bubble, {
"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 {
id: bubble
......@@ -321,7 +239,8 @@ Control {
function getBaseColor() {
var baseColor = isOutgoing ? JamiTheme.messageOutBgColor
: 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 we are replying to or editing the message
return Qt.darker(baseColor, 1.5)
......
......@@ -38,10 +38,6 @@ Item {
Object.assign(JamiQmlUtils.accountCreationInputParaObject, inputPara)
return accountCreationInputParaObject
}
//to know if the chatview is being scrolled
property bool isChatviewScrolling
//chatviewHeader
property var messagingHeaderRectRowLayout
// MessageBar buttons in mainview points
property var mainViewRectObj
......
......@@ -150,7 +150,11 @@ Rectangle {
? Qt.createComponent("qrc:/webengine/emojipicker/EmojiPicker.qml")
: Qt.createComponent("qrc:/nowebengine/EmojiPicker.qml")
messageBar.emojiPicker =
component.createObject(messageBar, {x: setXposition(), y: setYposition()});
component.createObject(messageBar, {
x: setXposition(),
y: setYposition(),
listView: null
});
if (messageBar.emojiPicker === null) {
console.log("Error creating emojiPicker in chatViewFooter");
}
......
......@@ -260,7 +260,6 @@ Rectangle {
}
}
Component.onCompleted: JamiQmlUtils.messagingHeaderRectRowLayout = messagingHeaderRectRowLayout
}
CustomBorder {
......
......@@ -21,6 +21,8 @@ import QtQuick
Rectangle {
id: root
required property ListView listView
signal emojiIsPicked(string content)
function openEmojiPicker() {}
function closeEmojiPicker() {}
......
......@@ -23,6 +23,7 @@ import Qt5Compat.GraphicalEffects
import QtWebEngine
import QtWebChannel
import net.jami.Models 1.1
import net.jami.Constants 1.1
import net.jami.Adapters 1.1
......@@ -31,8 +32,17 @@ import "../"
Popup {
id: root
required property ListView listView
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() {
root.open()
emojiPickerWebView.runJavaScript(
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment