diff --git a/matrique.pro b/matrique.pro
index 5a6d65a..f27d296 100644
--- a/matrique.pro
+++ b/matrique.pro
@@ -1,7 +1,9 @@
QT += quick widgets multimedia
CONFIG += c++14
CONFIG += object_parallel_to_source
-CONFIG += qtquickcompiler
+
+# Enable this to use QtQuick Compiler.
+#CONFIG += qtquickcompiler
TARGET = matrique
@@ -75,10 +77,9 @@ DISTFILES += \
ButtonDelegate.qml \
SideNav.qml \
RoomListForm.qml \
- RoomDetailForm.qml \
Room.qml \
Setting.qml \
- qml/js/md.js
+ qml/js/md.js \
HEADERS += \
src/controller.h \
diff --git a/qml/MatriqueSettings.qml b/qml/MatriqueSettings.qml
index 6bcdbb5..1c8ead1 100644
--- a/qml/MatriqueSettings.qml
+++ b/qml/MatriqueSettings.qml
@@ -4,7 +4,6 @@ import Qt.labs.settings 1.0
Settings {
property bool lazyLoad: true
- property bool asyncMessageDelegate
property bool richText
property bool pressAndHold
property bool rearrangeByActivity
diff --git a/qml/Setting.qml b/qml/Setting.qml
index 968ee5b..d268159 100644
--- a/qml/Setting.qml
+++ b/qml/Setting.qml
@@ -66,12 +66,6 @@ Page {
onCheckedChanged: MSettings.lazyLoad = checked
}
- Switch {
- text: "Force loading message delegates asynchronously"
- checked: MSettings.asyncMessageDelegate
- onCheckedChanged: MSettings.asyncMessageDelegate = checked
- }
-
Switch {
text: "Use RichText instead of StyledText"
checked: MSettings.richText
diff --git a/qml/component/AudioBubble.qml b/qml/component/AudioBubble.qml
deleted file mode 100644
index e01f5ae..0000000
--- a/qml/component/AudioBubble.qml
+++ /dev/null
@@ -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) : {}
- }
-
-}
diff --git a/qml/component/AutoLabel.qml b/qml/component/AutoLabel.qml
new file mode 100644
index 0000000..238c831
--- /dev/null
+++ b/qml/component/AutoLabel.qml
@@ -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)
+}
diff --git a/qml/component/AvatarContainer.qml b/qml/component/AvatarContainer.qml
deleted file mode 100644
index 64c4599..0000000
--- a/qml/component/AvatarContainer.qml
+++ /dev/null
@@ -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
- }
-}
diff --git a/qml/component/FileBubble.qml b/qml/component/FileBubble.qml
deleted file mode 100644
index 4ff77bd..0000000
--- a/qml/component/FileBubble.qml
+++ /dev/null
@@ -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: "File: " + content.body
- }
- }
-}
diff --git a/qml/component/GenericBubble.qml b/qml/component/GenericBubble.qml
new file mode 100644
index 0000000..369423e
--- /dev/null
+++ b/qml/component/GenericBubble.qml
@@ -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)
+ }
+}
diff --git a/qml/component/ImageBubble.qml b/qml/component/ImageBubble.qml
deleted file mode 100644
index 979c670..0000000
--- a/qml/component/ImageBubble.qml
+++ /dev/null
@@ -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()
- }
- }
- }
-}
diff --git a/qml/component/MessageBubble.qml b/qml/component/MessageBubble.qml
deleted file mode 100644
index 7e87cae..0000000
--- a/qml/component/MessageBubble.qml
+++ /dev/null
@@ -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
- }
-}
diff --git a/qml/component/MessageDelegate.qml b/qml/component/MessageDelegate.qml
index e007cbf..a78ab35 100644
--- a/qml/component/MessageDelegate.qml
+++ b/qml/component/MessageDelegate.qml
@@ -1,53 +1,184 @@
import QtQuick 2.9
import QtQuick.Controls 2.2
+import QtQuick.Layouts 1.3
import QtQuick.Controls.Material 2.2
import Matrique 0.1
import Matrique.Settings 0.1
-Item {
- readonly property bool hidden: marks === EventStatus.Redacted || marks === EventStatus.Hidden
- readonly property color background: MSettings.darkTheme ? "#242424" : "lightgrey"
+RowLayout {
+ readonly property bool avatarVisible: !(sentByMe || (aboveAuthor === author && section === aboveSection))
+ readonly property bool highlighted: !sentByMe
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
- width: delegateLoader.width
- height: delegateLoader.height
- anchors.right: !isState && sentByMe ? parent.right : undefined
- anchors.horizontalCenter: isState ? parent.horizontalCenter : undefined
+ Layout.alignment: sentByMe ? Qt.AlignRight : Qt.AlignLeft
- AutoMouseArea {
- anchors.fill: parent
+ spacing: 6
- 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 {
- id: delegateLoader
+ Rectangle {
+ Layout.preferredWidth: 40
+ Layout.preferredHeight: 40
+ Layout.alignment: Qt.AlignTop
- asynchronous: MSettings.asyncMessageDelegate
+ color: "transparent"
+ visible: !(sentByMe || avatarVisible)
+ }
- source: {
- if (eventType == "redaction" || hidden) return ""
- switch (eventType) {
- case "state":
- case "emote":
- return "StateBubble.qml"
- case "message":
- case "notice":
- return "MessageBubble.qml"
- case "image":
- return "ImageBubble.qml"
- case "audio":
- return "AudioBubble.qml"
- case "video":
- case "file":
- return "FileBubble.qml"
+ GenericBubble {
+ Layout.maximumWidth: messageListView.width - (!sentByMe ? 40 + messageRow.spacing : 0)
+
+ id: genericBubble
+
+ highlighted: !sentByMe
+ colored: highlighted && eventType === "notice"
+
+ contentItem: ColumnLayout {
+ id: messageColumn
+
+ spacing: 0
+
+ AutoLabel {
+ visible: messageRow.avatarVisible
+ 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: "File: " + 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 ""
}
}
}
diff --git a/qml/component/StateBubble.qml b/qml/component/StateBubble.qml
deleted file mode 100644
index 693c677..0000000
--- a/qml/component/StateBubble.qml
+++ /dev/null
@@ -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: "" + author.displayName + " " + display
-}
diff --git a/qml/component/StateDelegate.qml b/qml/component/StateDelegate.qml
new file mode 100644
index 0000000..376763f
--- /dev/null
+++ b/qml/component/StateDelegate.qml
@@ -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: "" + author.displayName + " " + 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"
+ }
+}
diff --git a/qml/component/TextDelegate.qml b/qml/component/TextDelegate.qml
deleted file mode 100644
index 9470178..0000000
--- a/qml/component/TextDelegate.qml
+++ /dev/null
@@ -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
- }
- }
-}
diff --git a/qml/form/RoomForm.qml b/qml/form/RoomForm.qml
index c94ec12..c8faaec 100644
--- a/qml/form/RoomForm.qml
+++ b/qml/form/RoomForm.qml
@@ -233,70 +233,67 @@ Item {
spacing: 8
boundsBehavior: Flickable.DragOverBounds
+ maximumFlickVelocity: 2048
model: MessageEventModel {
id: messageEventModel
room: currentRoom
}
- delegate: Column {
+ delegate: ColumnLayout {
readonly property bool hidden: marks === EventStatus.Redacted || marks === EventStatus.Hidden
+ id: delegateColumn
+
width: parent.width
height: hidden ? -8 : undefined
+
spacing: 8
- RowLayout {
- width: parent.width * 0.8
+ Label {
+ Layout.alignment: Qt.AlignHCenter
+
visible: section !== aboveSection && !hidden
- anchors.horizontalCenter: parent.horizontalCenter
- spacing: 8
- Rectangle {
- Layout.fillWidth: true
- height:2
- color: Material.accent
- }
+ text: section
+ color: "white"
+ verticalAlignment: Text.AlignVCenter
+ leftPadding: 8
+ rightPadding: 8
+ topPadding: 4
+ bottomPadding: 4
- Label {
- text: section
- color: Material.accent
- verticalAlignment: Text.AlignVCenter
- }
-
- Rectangle {
- Layout.fillWidth: true
- height:2
- color: Material.accent
+ background: Rectangle {
+ color: MSettings.darkTheme ? "#484848" : "grey"
}
}
- RowLayout {
- width: parent.width * 0.8
+ Label {
+ Layout.alignment: Qt.AlignHCenter
+
visible: readMarker === true && index !== 0
- anchors.horizontalCenter: parent.horizontalCenter
- spacing: 8
- Rectangle {
- Layout.fillWidth: true
- height:2
- color: Material.accent
- }
+ text: "And Now"
+ color: "white"
+ verticalAlignment: Text.AlignVCenter
+ leftPadding: 8
+ rightPadding: 8
+ topPadding: 4
+ bottomPadding: 4
- Label {
- text: "And Now"
- color: Material.accent
- verticalAlignment: Text.AlignVCenter
- }
-
- Rectangle {
- Layout.fillWidth: true
- height:2
- color: Material.accent
+ background: Rectangle {
+ color: MSettings.darkTheme ? "#484848" : "grey"
}
}
- 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
diff --git a/qml/main.qml b/qml/main.qml
index 1f06ca1..a2d4186 100644
--- a/qml/main.qml
+++ b/qml/main.qml
@@ -65,7 +65,7 @@ ApplicationWindow {
parent: null
- connection: matriqueController.isLogin ? window.connection : null
+ connection: window.connection
}
Setting {
diff --git a/qml/menu/MessageContextMenu.qml b/qml/menu/MessageContextMenu.qml
index dd2b92d..91c8e03 100644
--- a/qml/menu/MessageContextMenu.qml
+++ b/qml/menu/MessageContextMenu.qml
@@ -18,13 +18,13 @@ Menu {
visible: isFile
height: visible ? undefined : 0
text: "Open Externally"
- onTriggered: delegateLoader.item.downloadAndOpen()
+ onTriggered: messageRow.openExternally()
}
MenuItem {
visible: isFile
height: visible ? undefined : 0
text: "Save As"
- onTriggered: delegateLoader.item.saveFileAs()
+ onTriggered: messageRow.saveFileAs()
}
MenuItem {
visible: sentByMe
diff --git a/res.qrc b/res.qrc
index e2c99a1..71c1cf5 100644
--- a/res.qrc
+++ b/res.qrc
@@ -14,16 +14,9 @@
asset/img/icon.png
js/md.js
qml/component/MessageDelegate.qml
- qml/component/MessageBubble.qml
- qml/component/ImageBubble.qml
- qml/component/StateBubble.qml
qml/component/DownloadableContent.qml
- qml/component/FileBubble.qml
- qml/component/AvatarContainer.qml
qml/form/RoomListForm.qml
- qml/component/AudioBubble.qml
qml/Setting.qml
- qml/component/TextDelegate.qml
qml/component/EmojiPicker.qml
qml/component/EmojiButton.qml
qml/component/AutoImage.qml
@@ -33,5 +26,8 @@
qml/MatriqueSettings.qml
qml/menu/MessageContextMenu.qml
qml/menu/RoomContextMenu.qml
+ qml/component/GenericBubble.qml
+ qml/component/StateDelegate.qml
+ qml/component/AutoLabel.qml