-
Nicolas Werner authoredNicolas Werner authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
ChatPage.qml 8.46 KiB
import QtQuick 2.0
import QtQuick.Layouts 1.0
import Sailfish.Pickers 1.0
import Sailfish.Silica 1.0
import Sailfish.Silica.private 1.0
import dev.neko.spoon 1.0
Page {
id: chatPage
property alias room: chatView.model
// The effective value will be restricted by ApplicationWindow.allowedOrientations
allowedOrientations: Orientation.All
SilicaFlickable {
anchors.fill: parent
Column {
anchors.fill: parent
PageHeader {
id: header
title: room.name
}
SilicaListView {
id: chatView
property bool atEnd: false
property int maxIndex: -1
height: parent.height - header.height
contentHeight: height
cacheBuffer: 1000
clip: true
boundsBehavior: Flickable.StopAtBounds
anchors.left: parent.left
anchors.right: parent.right
ListView.onAdd: {
console.log("atYEnd::" + atYEnd);
atEnd = atYEnd;
}
onCountChanged: {
console.log("atEnd::" + atEnd);
if (atEnd) {
scrollToBottom();
currentIndex = count - 1;
}
}
onMovementEnded: {
atEnd = false;
console.log("movement ended");
if (chatView.atYBeginning) {
console.log("load older messages");
room.fetchOlderMessages();
}
if (chatView.atYEnd) {
console.log("at end");
atEnd = true;
} else {
console.log("not at end");
atEnd = false;
}
var lastIndex = maxIndex;
for (var child in chatView.contentItem.children) {
if (chatView.contentItem.children[child].isFullyVisible && chatView.contentItem.children[child].index > maxIndex)
lastIndex = chatView.contentItem.children[child].index;
}
if (lastIndex > maxIndex)
maxIndex = lastIndex;
}
onMaxIndexChanged: {
console.log("max index: " + maxIndex);
room.markRead(maxIndex);
}
Component.onCompleted: {
maxIndex = room.lastRead();
if (maxIndex = count - 1)
atEnd = true;
positionViewAtIndex(maxIndex, ListView.Contain);
}
ScrollDecorator {
flickable: chatView
}
footer: Row {
anchors.left: parent.left
anchors.right: parent.right
height: messageText.height
TextArea {
id: messageText
anchors.bottom: parent.bottom
placeholderText: qsTr("Enter your message")
label: qsTr("Matrix")
labelVisible: true
wrapMode: Text.Wrap
width: parent.width - sendButton.width
}
IconButton {
id: sendButton
anchors.top: parent.top
icon.source: "image://theme/icon-m-send"
onClicked: {
if (messageText.text != "")
room.sendTextMessage(messageText.text);
messageText.text = "";
}
}
}
delegate: ListItem {
id: messageItem
contentHeight: content.height + 2 * Theme.paddingMedium
width: chatView.width
BubbleBackground {
id: bubble
property int fullMessageWidth: parent.width - 2 * Theme.paddingLarge
property int yoff: Math.round(messageItem.y - chatView.contentY - 1)
property bool isFullyVisible: yoff + messageItem.height < chatView.height
property int index: model.index
color: Theme.rgba(Theme.primaryColor, Theme.opacityFaint)
opacity: model.IsSender ? Theme.opacityFaint : Theme.opacityHigh
radius: Theme.paddingLarge
height: content.implicitHeight + 2 * Theme.paddingSmall
width: content.implicitWidth + 2 * Theme.paddingSmall
roundedCorners: BubbleBackground.NoCorners | (model.IsSender ? BubbleBackground.BottomLeft : BubbleBackground.BottomRight)
anchors {
topMargin: Theme.paddingSmall
bottomMargin: Theme.paddingSmall
leftMargin: Theme.paddingMedium
rightMargin: Theme.paddingMedium
right: model.IsSender ? parent.right : undefined
left: !model.IsSender ? parent.left : undefined
top: parent.top
bottom: parent.bottom
}
Behavior on width {
NumberAnimation {
duration: 100
easing.type: Easing.InOutQuad
}
}
}
ColumnLayout {
id: content
anchors {
margins: Theme.paddingSmall
right: model.IsSender ? bubble.right : undefined
left: !model.IsSender ? bubble.left : undefined
top: bubble.top
bottom: bubble.bottom
}
Text {
text: room.userIdToUserName(model.UserId)
color: room.userColor(model.UserId, "#00000000")
Layout.alignment: model.IsSender ? Qt.AlignRight : Qt.AlignLeft
horizontalAlignment: Text.AlignRight
}
Message {
id: loader
Layout.alignment: model.IsSender ? Qt.AlignRight : Qt.AlignLeft
modelData: model
opacity: 1
}
Text {
id: ts
Layout.alignment: model.IsSender ? Qt.AlignRight : Qt.AlignLeft
text: model.Timestamp.toLocaleString()
color: Theme.highlightColor
font.pixelSize: Theme.fontSizeTiny
horizontalAlignment: Text.AlignRight
}
}
}
}
}
PushUpMenu {
MenuItem {
text: qsTr("Send image")
onClicked: pageStack.push(multiImagePickerDialog)
}
MenuItem {
text: qsTr("Send video")
onClicked: console.log("Clicked option 1")
}
MenuItem {
text: qsTr("Send audio")
onClicked: console.log("Clicked option 1")
}
MenuItem {
text: qsTr("Send file")
onClicked: console.log("Clicked option 1")
}
}
}
Component {
id: multiImagePickerDialog
MultiImagePickerDialog {
onAccepted: {
var urls = [];
var mimetypes = [];
for (var i = 0; i < selectedContent.count; ++i) {
urls.push(selectedContent.get(i).url);
mimetypes.push(selectedContent.get(i).mimeType);
}
room.sendImages(urls, mimetypes);
}
onRejected: selectedFiles = ""
}
}
}