Rewrite MessageDelegate.

This commit is contained in:
Black Hat 2018-09-04 14:58:41 +08:00
parent 0301590b44
commit 2f080f21ce
18 changed files with 272 additions and 323 deletions

View File

@ -1,7 +1,9 @@
QT += quick widgets multimedia QT += quick widgets multimedia
CONFIG += c++14 CONFIG += c++14
CONFIG += object_parallel_to_source CONFIG += object_parallel_to_source
CONFIG += qtquickcompiler
# Enable this to use QtQuick Compiler.
#CONFIG += qtquickcompiler
TARGET = matrique TARGET = matrique
@ -75,10 +77,9 @@ DISTFILES += \
ButtonDelegate.qml \ ButtonDelegate.qml \
SideNav.qml \ SideNav.qml \
RoomListForm.qml \ RoomListForm.qml \
RoomDetailForm.qml \
Room.qml \ Room.qml \
Setting.qml \ Setting.qml \
qml/js/md.js qml/js/md.js \
HEADERS += \ HEADERS += \
src/controller.h \ src/controller.h \

View File

@ -4,7 +4,6 @@ import Qt.labs.settings 1.0
Settings { Settings {
property bool lazyLoad: true property bool lazyLoad: true
property bool asyncMessageDelegate
property bool richText property bool richText
property bool pressAndHold property bool pressAndHold
property bool rearrangeByActivity property bool rearrangeByActivity

View File

@ -66,12 +66,6 @@ Page {
onCheckedChanged: MSettings.lazyLoad = checked onCheckedChanged: MSettings.lazyLoad = checked
} }
Switch {
text: "Force loading message delegates asynchronously"
checked: MSettings.asyncMessageDelegate
onCheckedChanged: MSettings.asyncMessageDelegate = checked
}
Switch { Switch {
text: "Use RichText instead of StyledText" text: "Use RichText instead of StyledText"
checked: MSettings.richText checked: MSettings.richText

View File

@ -1,50 +0,0 @@
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.2
import QtMultimedia 5.9
import Qt.labs.platform 1.0
AvatarContainer {
readonly property var downloadAndOpen: downloadable.downloadAndOpen
readonly property var saveFileAs: downloadable.saveFileAs
property bool playOnFinished: false
id: messageRow
DownloadableContent {
id: downloadable
width: downloadDelegate.width
height: downloadDelegate.height
TextDelegate {
id: downloadDelegate
maximumWidth: messageListView.width
highlighted: !sentByMe
timeLabelVisible: false
authorLabelVisible: false
displayText: content.info.duration / 1000 + '"'
MouseArea {
anchors.fill: parent
propagateComposedEvents: true
onClicked: {
if (downloadable.downloaded)
matriqueController.playAudio(progressInfo.localPath)
else
{
playOnFinished = true
currentRoom.downloadFile(eventId, StandardPaths.writableLocation(StandardPaths.CacheLocation) + "/" + eventId.replace(":", "_") + ".tmp")
}
}
}
}
onDownloadedChanged: downloaded && playOnFinished ? matriqueController.playAudio(progressInfo.localPath) : {}
}
}

View File

@ -0,0 +1,15 @@
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.2
import Matrique.Settings 0.1
Label {
property bool coloredBackground
color: coloredBackground ? "white": Material.foreground
wrapMode: Label.Wrap
linkColor: coloredBackground ? "white" : Material.accent
textFormat: MSettings.richText ? Text.RichText : Text.StyledText
onLinkActivated: Qt.openUrlExternally(link)
}

View File

@ -1,26 +0,0 @@
import QtQuick 2.9
import QtQuick.Controls 2.2
Row {
readonly property bool avatarVisible: !(sentByMe || (aboveAuthor === author && section === aboveSection))
spacing: 6
ImageStatus {
id: avatar
width: height
height: 40
round: false
visible: avatarVisible
source: author.avatarUrl != "" ? "image://mxc/" + author.avatarUrl : null
displayText: author.displayName
}
Rectangle {
width: height
height: 40
color: "transparent"
visible: !avatarVisible
}
}

View File

@ -1,28 +0,0 @@
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.2
AvatarContainer {
readonly property var downloadAndOpen: downloadable.downloadAndOpen
readonly property var saveFileAs: downloadable.saveFileAs
id: messageRow
DownloadableContent {
id: downloadable
width: downloadDelegate.width
height: downloadDelegate.height
TextDelegate {
id: downloadDelegate
maximumWidth: messageListView.width
highlighted: !sentByMe
timeLabelVisible: false
authorLabelVisible: false
displayText: "<b>File: </b>" + content.body
}
}
}

View File

@ -0,0 +1,24 @@
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.2
import Matrique.Settings 0.1
Control {
property bool highlighted: false
property bool colored: false
readonly property bool darkBackground: highlighted ? true : MSettings.darkTheme
readonly property color backgroundColor: MSettings.darkTheme ? "#242424" : "lightgrey"
padding: 12
background: Rectangle {
color: colored ? Material.accent : highlighted ? Material.primary : backgroundColor
}
AutoMouseArea {
anchors.fill: parent
onSecondaryClicked: Qt.createComponent("qrc:/qml/menu/MessageContextMenu.qml").createObject(this)
}
}

View File

@ -1,34 +0,0 @@
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.2
AvatarContainer {
readonly property var downloadAndOpen: downloadable.downloadAndOpen
readonly property var saveFileAs: downloadable.saveFileAs
Rectangle {
id: messageRect
width: messageImage.width + 24
height: messageImage.height + 24
color: sentByMe ? background : Material.primary
DownloadableContent {
id: downloadable
width: messageImage.width
height: messageImage.height
anchors.centerIn: parent
AutoImage {
id: messageImage
z: -4
sourceSize: 128
source: "image://mxc/" + (content.thumbnail_url ? content.thumbnail_url : content.url)
onClicked: downloadAndOpen()
}
}
}
}

View File

@ -1,20 +0,0 @@
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
import QtQuick.Controls.Material 2.2
AvatarContainer {
readonly property bool isNotice: eventType === "notice"
id: messageRow
TextDelegate {
maximumWidth: messageListView.width - (!sentByMe ? 40 + messageRow.spacing : 0)
flat: isNotice
highlighted: !sentByMe
timeLabelVisible: Math.abs(time - aboveTime) > 600000 || index == 0
authorLabelVisible: messageRow.avatarVisible
displayText: display
}
}

View File

@ -1,53 +1,184 @@
import QtQuick 2.9 import QtQuick 2.9
import QtQuick.Controls 2.2 import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
import QtQuick.Controls.Material 2.2 import QtQuick.Controls.Material 2.2
import Matrique 0.1 import Matrique 0.1
import Matrique.Settings 0.1 import Matrique.Settings 0.1
Item { RowLayout {
readonly property bool hidden: marks === EventStatus.Redacted || marks === EventStatus.Hidden readonly property bool avatarVisible: !(sentByMe || (aboveAuthor === author && section === aboveSection))
readonly property color background: MSettings.darkTheme ? "#242424" : "lightgrey" readonly property bool highlighted: !sentByMe
readonly property bool sentByMe: author === currentRoom.localUser readonly property bool sentByMe: author === currentRoom.localUser
readonly property bool isState: eventType === "state" || eventType === "emote" readonly property bool isText: eventType === "notice" || eventType === "message"
id: messageDelegate signal saveFileAs()
signal openExternally()
id: messageRow
z: -5 z: -5
width: delegateLoader.width
height: delegateLoader.height
anchors.right: !isState && sentByMe ? parent.right : undefined Layout.alignment: sentByMe ? Qt.AlignRight : Qt.AlignLeft
anchors.horizontalCenter: isState ? parent.horizontalCenter : undefined
AutoMouseArea { spacing: 6
anchors.fill: parent
onSecondaryClicked: Qt.createComponent("qrc:/qml/menu/MessageContextMenu.qml").createObject(this) ImageStatus {
Layout.preferredWidth: 40
Layout.preferredHeight: 40
Layout.alignment: Qt.AlignTop
round: false
visible: avatarVisible
source: author.avatarUrl != "" ? "image://mxc/" + author.avatarUrl : null
displayText: author.displayName
} }
Loader { Rectangle {
id: delegateLoader Layout.preferredWidth: 40
Layout.preferredHeight: 40
Layout.alignment: Qt.AlignTop
asynchronous: MSettings.asyncMessageDelegate color: "transparent"
visible: !(sentByMe || avatarVisible)
}
source: { GenericBubble {
if (eventType == "redaction" || hidden) return "" Layout.maximumWidth: messageListView.width - (!sentByMe ? 40 + messageRow.spacing : 0)
switch (eventType) {
case "state": id: genericBubble
case "emote":
return "StateBubble.qml" highlighted: !sentByMe
case "message": colored: highlighted && eventType === "notice"
case "notice":
return "MessageBubble.qml" contentItem: ColumnLayout {
case "image": id: messageColumn
return "ImageBubble.qml"
case "audio": spacing: 0
return "AudioBubble.qml"
case "video": AutoLabel {
case "file": visible: messageRow.avatarVisible
return "FileBubble.qml" text: author.displayName
Material.foreground: Material.accent
coloredBackground: highlighted
font.bold: true
}
AutoLabel {
Layout.fillWidth: true
text: display
visible: isText
coloredBackground: highlighted
}
Loader {
sourceComponent: {
switch (eventType) {
case "image":
return imageComponent
case "file":
return fileComponent
case "audio":
return audioComponent
}
}
active: eventType === "image" || eventType === "file" || eventType === "audio"
}
AutoLabel {
Layout.alignment: Qt.AlignRight
visible: Math.abs(time - aboveTime) > 600000 || index == 0
text: Qt.formatTime(time, "hh:mm")
coloredBackground: highlighted
Material.foreground: "grey"
font.pointSize: 8
}
}
Component {
id: imageComponent
DownloadableContent {
id: downloadable
width: messageImage.width
height: messageImage.height
AutoImage {
id: messageImage
z: -4
sourceSize: 128
source: "image://mxc/" + (content.thumbnail_url ? content.thumbnail_url : content.url)
onClicked: downloadAndOpen()
}
Component.onCompleted: {
messageRow.saveFileAs.connect(saveFileAs)
messageRow.openExternally.connect(downloadAndOpen)
}
}
}
Component {
id: fileComponent
AutoLabel {
Layout.fillWidth: true
id: downloadDelegate
text: "<b>File: </b>" + content.body
coloredBackground: highlighted
background: DownloadableContent {
id: downloadable
Component.onCompleted: {
messageRow.saveFileAs.connect(saveFileAs)
messageRow.openExternally.connect(downloadAndOpen)
}
}
}
}
Component {
id: audioComponent
AutoLabel {
id: downloadDelegate
text: content.info.duration / 1000 + '"'
coloredBackground: highlighted
MouseArea {
anchors.fill: parent
propagateComposedEvents: true
onClicked: {
if (downloadable.downloaded)
matriqueController.playAudio(progressInfo.localPath)
else
{
playOnFinished = true
currentRoom.downloadFile(eventId, StandardPaths.writableLocation(StandardPaths.CacheLocation) + "/" + eventId.replace(":", "_") + ".tmp")
}
}
}
background: DownloadableContent {
id: downloadable
onDownloadedChanged: downloaded && playOnFinished ? matriqueController.playAudio(progressInfo.localPath) : {}
Component.onCompleted: {
messageRow.saveFileAs.connect(saveFileAs)
messageRow.openExternally.connect(downloadAndOpen)
}
}
} }
return ""
} }
} }
} }

View File

@ -1,12 +0,0 @@
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.2
TextDelegate {
maximumWidth: messageListView.width
highlighted: eventType === "emote"
timeLabelVisible: false
authorLabelVisible: false
displayText: "<b>" + author.displayName + "</b> " + display
}

View File

@ -0,0 +1,23 @@
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
import QtQuick.Controls.Material 2.2
import Matrique.Settings 0.1
Label {
Layout.alignment: Qt.AlignHCenter
text: "<b>" + author.displayName + "</b> " + display
color: "white"
padding: 8
wrapMode: Label.Wrap
linkColor: "white"
textFormat: MSettings.richText ? Text.RichText : Text.StyledText
onLinkActivated: Qt.openUrlExternally(link)
background: Rectangle {
color: MSettings.darkTheme ? "#484848" : "grey"
}
}

View File

@ -1,61 +0,0 @@
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.2
import QtQuick.Layouts 1.3
import Matrique.Settings 0.1
Rectangle {
property bool flat: false
property bool highlighted: false
property string displayText: ""
property alias timeLabelVisible: timeText.visible
property alias authorLabelVisible: authorText.visible
property int maximumWidth
readonly property bool darkBackground: highlighted && !flat
id: messageRect
width: Math.min(Math.max(messageText.implicitWidth, (timeText.visible ? timeText.implicitWidth : 0), (authorLabelVisible ? authorText.implicitWidth : 0)) + 24, maximumWidth)
height: (authorText.visible ? authorText.implicitHeight : 0) + messageText.implicitHeight + (timeText.visible ? timeText.implicitHeight : 0) + 24
color: flat ? "transparent" : highlighted ? Material.primary : background
border.color: Material.primary
border.width: flat ? 2 : 0
ColumnLayout {
id: messageColumn
anchors.fill: parent
anchors.margins: 12
spacing: 0
Label {
id: authorText
text: author.displayName
color: darkBackground ? "white" : Material.accent
font.bold: true
}
Label {
id: messageText
Layout.maximumWidth: parent.width
text: displayText
color: darkBackground ? "white": Material.foreground
wrapMode: Label.Wrap
linkColor: darkBackground ? "white" : Material.accent
textFormat: MSettings.richText ? Text.RichText : Text.StyledText
onLinkActivated: Qt.openUrlExternally(link)
}
Label {
id: timeText
Layout.alignment: Qt.AlignRight
text: Qt.formatTime(time, "hh:mm")
color: darkBackground ? "white" : "grey"
font.pointSize: 8
}
}
}

View File

@ -233,70 +233,67 @@ Item {
spacing: 8 spacing: 8
boundsBehavior: Flickable.DragOverBounds boundsBehavior: Flickable.DragOverBounds
maximumFlickVelocity: 2048
model: MessageEventModel { model: MessageEventModel {
id: messageEventModel id: messageEventModel
room: currentRoom room: currentRoom
} }
delegate: Column { delegate: ColumnLayout {
readonly property bool hidden: marks === EventStatus.Redacted || marks === EventStatus.Hidden readonly property bool hidden: marks === EventStatus.Redacted || marks === EventStatus.Hidden
id: delegateColumn
width: parent.width width: parent.width
height: hidden ? -8 : undefined height: hidden ? -8 : undefined
spacing: 8 spacing: 8
RowLayout { Label {
width: parent.width * 0.8 Layout.alignment: Qt.AlignHCenter
visible: section !== aboveSection && !hidden visible: section !== aboveSection && !hidden
anchors.horizontalCenter: parent.horizontalCenter
spacing: 8
Rectangle { text: section
Layout.fillWidth: true color: "white"
height:2 verticalAlignment: Text.AlignVCenter
color: Material.accent leftPadding: 8
} rightPadding: 8
topPadding: 4
bottomPadding: 4
Label { background: Rectangle {
text: section color: MSettings.darkTheme ? "#484848" : "grey"
color: Material.accent
verticalAlignment: Text.AlignVCenter
}
Rectangle {
Layout.fillWidth: true
height:2
color: Material.accent
} }
} }
RowLayout { Label {
width: parent.width * 0.8 Layout.alignment: Qt.AlignHCenter
visible: readMarker === true && index !== 0 visible: readMarker === true && index !== 0
anchors.horizontalCenter: parent.horizontalCenter
spacing: 8
Rectangle { text: "And Now"
Layout.fillWidth: true color: "white"
height:2 verticalAlignment: Text.AlignVCenter
color: Material.accent leftPadding: 8
} rightPadding: 8
topPadding: 4
bottomPadding: 4
Label { background: Rectangle {
text: "And Now" color: MSettings.darkTheme ? "#484848" : "grey"
color: Material.accent
verticalAlignment: Text.AlignVCenter
}
Rectangle {
Layout.fillWidth: true
height:2
color: Material.accent
} }
} }
MessageDelegate {} MessageDelegate {
visible: eventType === "notice" || eventType === "message" || eventType === "image" || eventType === "video" || eventType === "audio" || eventType === "file"
}
StateDelegate {
Layout.maximumWidth: messageListView.width * 0.8
visible: eventType === "emote" || eventType === "state"
}
} }
ScrollBar.vertical: messageListViewScrollBar ScrollBar.vertical: messageListViewScrollBar

View File

@ -65,7 +65,7 @@ ApplicationWindow {
parent: null parent: null
connection: matriqueController.isLogin ? window.connection : null connection: window.connection
} }
Setting { Setting {

View File

@ -18,13 +18,13 @@ Menu {
visible: isFile visible: isFile
height: visible ? undefined : 0 height: visible ? undefined : 0
text: "Open Externally" text: "Open Externally"
onTriggered: delegateLoader.item.downloadAndOpen() onTriggered: messageRow.openExternally()
} }
MenuItem { MenuItem {
visible: isFile visible: isFile
height: visible ? undefined : 0 height: visible ? undefined : 0
text: "Save As" text: "Save As"
onTriggered: delegateLoader.item.saveFileAs() onTriggered: messageRow.saveFileAs()
} }
MenuItem { MenuItem {
visible: sentByMe visible: sentByMe

10
res.qrc
View File

@ -14,16 +14,9 @@
<file>asset/img/icon.png</file> <file>asset/img/icon.png</file>
<file>js/md.js</file> <file>js/md.js</file>
<file>qml/component/MessageDelegate.qml</file> <file>qml/component/MessageDelegate.qml</file>
<file>qml/component/MessageBubble.qml</file>
<file>qml/component/ImageBubble.qml</file>
<file>qml/component/StateBubble.qml</file>
<file>qml/component/DownloadableContent.qml</file> <file>qml/component/DownloadableContent.qml</file>
<file>qml/component/FileBubble.qml</file>
<file>qml/component/AvatarContainer.qml</file>
<file>qml/form/RoomListForm.qml</file> <file>qml/form/RoomListForm.qml</file>
<file>qml/component/AudioBubble.qml</file>
<file>qml/Setting.qml</file> <file>qml/Setting.qml</file>
<file>qml/component/TextDelegate.qml</file>
<file>qml/component/EmojiPicker.qml</file> <file>qml/component/EmojiPicker.qml</file>
<file>qml/component/EmojiButton.qml</file> <file>qml/component/EmojiButton.qml</file>
<file>qml/component/AutoImage.qml</file> <file>qml/component/AutoImage.qml</file>
@ -33,5 +26,8 @@
<file>qml/MatriqueSettings.qml</file> <file>qml/MatriqueSettings.qml</file>
<file>qml/menu/MessageContextMenu.qml</file> <file>qml/menu/MessageContextMenu.qml</file>
<file>qml/menu/RoomContextMenu.qml</file> <file>qml/menu/RoomContextMenu.qml</file>
<file>qml/component/GenericBubble.qml</file>
<file>qml/component/StateDelegate.qml</file>
<file>qml/component/AutoLabel.qml</file>
</qresource> </qresource>
</RCC> </RCC>