Commit aeabbb7c authored by Ronan Abhamon's avatar Ronan Abhamon

unstable (chat refactoring)

parent 14aa6a9c
......@@ -267,6 +267,7 @@
<file>ui/modules/Linphone/Calls/CallControls.qml</file>
<file>ui/modules/Linphone/Calls/Calls.qml</file>
<file>ui/modules/Linphone/CardBlock.qml</file>
<file>ui/modules/Linphone/Chat/Chat.js</file>
<file>ui/modules/Linphone/Chat/Chat.qml</file>
<file>ui/modules/Linphone/Chat/Event.qml</file>
<file>ui/modules/Linphone/Chat/FileMessage.qml</file>
......
// =============================================================================
// `Chat.qml` Logic.
// =============================================================================
function initView () {
chat.tryToLoadMoreEntries = false
chat.bindToEnd = true
chat.positionViewAtEnd()
}
function loadMoreEntries () {
if (chat.atYBeginning && !chat.tryToLoadMoreEntries) {
chat.tryToLoadMoreEntries = true
chat.positionViewAtBeginning()
proxyModel.loadMoreEntries()
}
}
function getComponentFromEntry (chatEntry) {
if (chatEntry.fileName) {
return 'FileMessage.qml'
}
if (chatEntry.type === ChatModel.CallEntry) {
return 'Event.qml'
}
return chatEntry.isOutgoing ? 'OutgoingMessage.qml' : 'IncomingMessage.qml'
}
function handleCurrentItemChanged (currentItem) {
// Go to last item only!
if (!chat.bindToEnd || !currentItem || chat.currentIndex + 1 !== chat.count) {
return
}
var chatHeight = chat.height
var messageY = currentItem.mapToItem(chat.contentItem, 0, 0).y
var messageHeight = currentItem.height
console.log(chat.contentY, chatHeight, messageY)
if (chat.contentY <= messageY) {
chat.contentY = messageY
}
chat.currentIndex = -1
}
function handleFilesDropped (files) {
chat.bindToEnd = true
files.forEach(proxyModel.sendFileMessage)
}
function handleMoreEntriesLoaded (n) {
chat.positionViewAtIndex(n - 1, ListView.Beginning)
chat.tryToLoadMoreEntries = false
}
function handleMovementEnded () {
if (chat.atYEnd) {
chat.bindToEnd = true
}
}
function handleMovementStarted () {
chat.bindToEnd = false
}
function handleDataChanged (_, bottomRight) {
var n = chat.count
var index = bottomRight.row
if (chat.bindToEnd && index + 1 === n) {
chat.currentIndex = index
}
}
function sendMessage (text) {
textArea.text = ''
chat.bindToEnd = true
proxyModel.sendMessage(text)
}
......@@ -5,16 +5,14 @@ import QtQuick.Layouts 1.3
import Common 1.0
import Linphone 1.0
import Linphone.Styles 1.0
import Utils 1.0
import 'Chat.js' as Logic
// =============================================================================
Rectangle {
property alias proxyModel: chat.model
property bool _bindToEnd: false
property var _contactObserver: SipAddressesModel.getContactObserver(proxyModel.sipAddress)
// ---------------------------------------------------------------------------
signal messageToSend (string text)
......@@ -32,30 +30,17 @@ Rectangle {
// -----------------------------------------------------------------------
property bool _tryToLoadMoreEntries: true
// -----------------------------------------------------------------------
function _loadMoreEntries () {
if (atYBeginning && !_tryToLoadMoreEntries) {
_tryToLoadMoreEntries = true
positionViewAtBeginning()
proxyModel.loadMoreEntries()
}
}
function _initView () {
_tryToLoadMoreEntries = false
_bindToEnd = true
positionViewAtEnd()
}
property bool bindToEnd: false
property bool tryToLoadMoreEntries: true
property var contactObserver: SipAddressesModel.getContactObserver(proxyModel.sipAddress)
// -----------------------------------------------------------------------
Layout.fillHeight: true
Layout.fillWidth: true
highlightFollowsCurrentItem: false
section {
criteria: ViewSection.FullString
delegate: sectionHeading
......@@ -64,32 +49,12 @@ Rectangle {
// -----------------------------------------------------------------------
Component.onCompleted: {
function goToEnd () {
return Utils.setTimeout(chat, 100, function () {
if (_bindToEnd) {
positionViewAtEnd()
}
return goToEnd()
})
}
goToEnd()
// First render.
_initView()
}
// -----------------------------------------------------------------------
onMovementStarted: _bindToEnd = false
onMovementEnded: {
if (atYEnd) {
_bindToEnd = true
}
}
Component.onCompleted: Logic.initView()
onContentYChanged: _loadMoreEntries()
onContentYChanged: Logic.loadMoreEntries()
onCurrentItemChanged: Logic.handleCurrentItemChanged(currentItem)
onMovementEnded: Logic.handleMovementEnded()
onMovementStarted: Logic.handleMovementStarted()
// -----------------------------------------------------------------------
......@@ -99,12 +64,9 @@ Rectangle {
// When the view is changed (for example `Calls` -> `Messages`),
// the position is set at end and it can be possible to load
// more entries.
onEntryTypeFilterChanged: chat._initView()
onMoreEntriesLoaded: {
chat.positionViewAtIndex(n - 1, ListView.Beginning)
chat._tryToLoadMoreEntries = false
}
onEntryTypeFilterChanged: Logic.initView()
onMoreEntriesLoaded: Logic.handleMoreEntriesLoaded(n)
onDataChanged: Logic.handleDataChanged(topLeft, bottomRight)
}
// -----------------------------------------------------------------------
......@@ -171,45 +133,18 @@ Rectangle {
leftMargin: ChatStyle.entry.leftMargin
right: parent ? parent.right : undefined
// Ugly. I admit it, but it exists a problem, without these
// lines the extra content message is truncated.
// I have no other solution at this moment with `anchors`
// properties... The messages use the `implicitWidth/Height`
// and `width/Height` attrs and is not easy to found a fix.
rightMargin: ChatStyle.entry.deleteIconSize +
ChatStyle.entry.message.extraContent.spacing +
ChatStyle.entry.message.extraContent.rightMargin +
ChatStyle.entry.message.extraContent.leftMargin +
ChatStyle.entry.message.outgoing.sendIconSize
}
color: ChatStyle.color
implicitHeight: layout.height + ChatStyle.entry.bottomMargin
// ---------------------------------------------------------------------
// Avoid the use of explicit qrc paths.
Component {
id: event
Event {}
}
Component {
id: incomingMessage
IncomingMessage {}
}
Component {
id: outgoingMessage
OutgoingMessage {}
}
Component {
id: fileMessage
FileMessage {}
}
// ---------------------------------------------------------------------
MouseArea {
id: mouseArea
......@@ -228,29 +163,22 @@ Rectangle {
Layout.alignment: Qt.AlignTop
Layout.preferredHeight: ChatStyle.entry.lineHeight
Layout.preferredWidth: ChatStyle.entry.time.width
color: ChatStyle.entry.time.color
font.pointSize: ChatStyle.entry.time.fontSize
text: $chatEntry.timestamp.toLocaleString(
Qt.locale(App.locale),
'hh:mm'
)
verticalAlignment: Text.AlignVCenter
}
// Display content.
Loader {
Layout.fillWidth: true
sourceComponent: {
if ($chatEntry.fileName) {
return fileMessage
}
if ($chatEntry.type === ChatModel.CallEntry) {
return event
}
return $chatEntry.isOutgoing ? outgoingMessage : incomingMessage
}
source: Logic.getComponentFromEntry($chatEntry)
}
}
}
......@@ -263,27 +191,22 @@ Rectangle {
Borders {
Layout.fillWidth: true
Layout.preferredHeight: ChatStyle.sendArea.height +
ChatStyle.sendArea.border.width
Layout.preferredHeight: ChatStyle.sendArea.height + ChatStyle.sendArea.border.width
borderColor: ChatStyle.sendArea.border.color
topWidth: ChatStyle.sendArea.border.width
DroppableTextArea {
id: textArea
anchors.fill: parent
dropEnabled: SettingsModel.fileTransferUrl.length > 0
dropDisabledReason: qsTr('noFileTransferUrl')
placeholderText: qsTr('newMessagePlaceholder')
onDropped: {
_bindToEnd = true
files.forEach(proxyModel.sendFileMessage)
}
onValidText: {
this.text = ''
_bindToEnd = true
proxyModel.sendMessage(text)
}
onDropped: Logic.handleFilesDropped(files)
onValidText: Logic.sendMessage(text)
}
}
}
......
......@@ -27,8 +27,8 @@ Row {
height: ChatStyle.entry.message.incoming.avatarSize
width: ChatStyle.entry.message.incoming.avatarSize
image: _contactObserver.contact ? _contactObserver.contact.avatar : ''
username: LinphoneUtils.getContactUsername(_contactObserver.contact || proxyModel.sipAddress)
image: chat.contactObserver.contact ? chat.contactObserver.contact.avatar : ''
username: LinphoneUtils.getContactUsername(chat.contactObserver.contact || proxyModel.sipAddress)
}
}
......
......@@ -20,8 +20,8 @@ RowLayout {
Avatar {
anchors.centerIn: parent
height: ChatStyle.entry.message.incoming.avatarSize
image: _contactObserver.contact ? _contactObserver.contact.avatar : ''
username: LinphoneUtils.getContactUsername(_contactObserver.contact || proxyModel.sipAddress)
image: chat.contactObserver.contact ? chat.contactObserver.contact.avatar : ''
username: LinphoneUtils.getContactUsername(chat.contactObserver.contact || proxyModel.sipAddress)
width: ChatStyle.entry.message.incoming.avatarSize
// The avatar is only visible for the first message of a incoming messages sequence.
......
// =============================================================================
// `Message.qml` Logic.
// =============================================================================
// See: `ensureVisible` on http://doc.qt.io/qt-5/qml-qtquick-textedit.html
function ensureVisible (cursor) {
// Case 1: No focused.
......
......@@ -59,7 +59,7 @@ Item {
// See http://doc.qt.io/qt-5/qml-qtquick-text.html#textFormat-prop
// and http://doc.qt.io/qt-5/richtext-html-subset.html
textFormat: Text.RichText // To supports links and imgs.
wrapMode: TextEdit.WordWrap
wrapMode: TextEdit.Wrap
onCursorRectangleChanged: Logic.ensureVisible(cursorRectangle)
onLinkActivated: Qt.openUrlExternally(link)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment