1
0
Fork 0
mirror of https://git.jami.net/savoirfairelinux/jami-client-qt.git synced 2025-07-21 16:05:26 +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:
Andreas Traczyk 2023-02-10 17:38:17 -05:00
parent 42a46fe165
commit 4612d5318b
8 changed files with 112 additions and 127 deletions

View file

@ -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()
}

View file

@ -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,22 +33,79 @@ 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
onOpened: {
root.closeWithoutAnimation = false
onAddMoreEmoji: {
JamiQmlUtils.updateMessageBarButtonsPoints()
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() {
var model = ["👍", "👎", "😂"]
var cur = []
@ -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

View file

@ -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)

View file

@ -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

View file

@ -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");
}

View file

@ -260,7 +260,6 @@ Rectangle {
}
}
Component.onCompleted: JamiQmlUtils.messagingHeaderRectRowLayout = messagingHeaderRectRowLayout
}
CustomBorder {

View file

@ -21,6 +21,8 @@ import QtQuick
Rectangle {
id: root
required property ListView listView
signal emojiIsPicked(string content)
function openEmojiPicker() {}
function closeEmojiPicker() {}

View file

@ -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(