Compare commits

..

No commits in common. "117bfb4790961b8c327b2a4a197987a80b9e4dec" and "9adb73eebf2c2e8958bfe4a2e9154d7ad9dfd43f" have entirely different histories.

8 changed files with 175 additions and 426 deletions

View File

@ -14,7 +14,7 @@ import Spectral.Menu.Timeline 2.0
import Spectral.Font 0.1
import Spectral.Effect 2.0
RowLayout {
ColumnLayout {
readonly property bool avatarVisible: !sentByMe && showAuthor
readonly property bool sentByMe: author === currentRoom.localUser
@ -23,175 +23,196 @@ RowLayout {
id: root
spacing: 4
spacing: 0
onDownloadedChanged: if (downloaded && openOnFinished) openSavedFile()
z: -5
Label {
Layout.leftMargin: 48
Avatar {
Layout.preferredWidth: 36
Layout.preferredHeight: 36
Layout.alignment: Qt.AlignBottom
text: author.displayName
visible: avatarVisible
hint: author.displayName
source: author.avatarMediaId
Component {
id: userDetailDialog
UserDetailDialog {}
}
RippleEffect {
anchors.fill: parent
circular: true
onClicked: userDetailDialog.createObject(ApplicationWindow.overlay, {"room": currentRoom, "user": author}).open()
}
font.pixelSize: 13
verticalAlignment: Text.AlignVCenter
}
Label {
Layout.preferredWidth: 36
Layout.preferredHeight: 36
RowLayout {
z: -5
visible: !(sentByMe || avatarVisible)
}
id: messageRow
Control {
Layout.maximumWidth: messageListView.width - (!sentByMe ? 36 + root.spacing : 0) - 48
spacing: 4
padding: 12
Avatar {
Layout.preferredWidth: 32
Layout.preferredHeight: 32
Layout.alignment: Qt.AlignTop
contentItem: RowLayout {
ToolButton {
contentItem: MaterialIcon {
icon: progressInfo.completed ? "\ue5ca" : "\ue2c4"
}
visible: avatarVisible
hint: author.displayName
source: author.avatarMediaId
onClicked: progressInfo.completed ? openSavedFile() : saveFileAs()
Component {
id: userDetailDialog
UserDetailDialog {}
}
ColumnLayout {
Label {
Layout.fillWidth: true
text: display
wrapMode: Label.Wrap
font.pixelSize: 18
font.weight: Font.Medium
font.capitalization: Font.AllUppercase
}
Label {
Layout.fillWidth: true
text: progressInfo.active ? (humanSize(progressInfo.progress) + "/" + humanSize(progressInfo.total)) : humanSize(content.info ? content.info.size : 0)
color: MPalette.lighter
wrapMode: Label.Wrap
}
}
}
background: Rectangle {
color: MPalette.background
radius: 18
Rectangle {
anchors.top: parent.top
anchors.left: parent.left
width: parent.width / 2
height: parent.height / 2
visible: true
color: sentByMe ? MPalette.background : eventType === "notice" ? MPalette.primary : MPalette.accent
radius: 5
}
Rectangle {
anchors.top: parent.top
anchors.right: parent.right
width: parent.width / 2
height: parent.height / 2
visible: true
color: sentByMe ? MPalette.background : eventType === "notice" ? MPalette.primary : MPalette.accent
radius: 5
}
Rectangle {
anchors.bottom: parent.bottom
anchors.left: parent.left
width: parent.width / 2
height: parent.height / 2
visible: true
color: sentByMe ? MPalette.background : eventType === "notice" ? MPalette.primary : MPalette.accent
radius: 5
}
Rectangle {
anchors.bottom: parent.bottom
anchors.right: parent.right
width: parent.width / 2
height: parent.height / 2
visible: true
color: sentByMe ? MPalette.background : eventType === "notice" ? MPalette.primary : MPalette.accent
radius: 5
}
AutoMouseArea {
RippleEffect {
anchors.fill: parent
id: messageMouseArea
circular: true
onSecondaryClicked: {
var contextMenu = fileDelegateContextMenu.createObject(ApplicationWindow.overlay)
contextMenu.viewSource.connect(function() {
messageSourceDialog.createObject(ApplicationWindow.overlay, {"sourceText": toolTip}).open()
})
contextMenu.downloadAndOpen.connect(downloadAndOpen)
contextMenu.saveFileAs.connect(saveFileAs)
contextMenu.reply.connect(function() {
roomPanelInput.replyUser = author
roomPanelInput.replyEventID = eventId
roomPanelInput.replyContent = message
roomPanelInput.isReply = true
roomPanelInput.focus()
})
contextMenu.redact.connect(function() {
currentRoom.redactEvent(eventId)
})
contextMenu.popup()
onClicked: userDetailDialog.createObject(ApplicationWindow.overlay, {"room": currentRoom, "user": author}).open()
}
}
Label {
Layout.preferredWidth: 32
Layout.preferredHeight: 32
Layout.alignment: Qt.AlignTop
visible: !(sentByMe || avatarVisible)
text: Qt.formatTime(time, "hh:mm AP")
color: "#5B7480"
font.pixelSize: 10
horizontalAlignment: Label.AlignHCenter
verticalAlignment: Label.AlignVCenter
}
Control {
Layout.maximumWidth: messageListView.width - (!sentByMe ? 32 + messageRow.spacing : 0) - 48
padding: 12
contentItem: RowLayout {
ToolButton {
contentItem: MaterialIcon {
icon: progressInfo.completed ? "\ue5ca" : "\ue2c4"
}
onClicked: progressInfo.completed ? openSavedFile() : saveFileAs()
}
Component {
id: messageSourceDialog
ColumnLayout {
Label {
Layout.alignment: Qt.AlignVCenter
MessageSourceDialog {}
text: display
font.pixelSize: 18
font.weight: Font.Medium
font.capitalization: Font.AllUppercase
}
Label {
text: progressInfo.active ? (humanSize(progressInfo.progress) + "/" + humanSize(progressInfo.total)) : humanSize(content.info ? content.info.size : 0)
color: MPalette.lighter
}
}
}
background: Rectangle {
color: MPalette.background
radius: 18
Rectangle {
anchors.top: parent.top
anchors.left: parent.left
width: parent.width / 2
height: parent.height / 2
visible: !sentByMe && (bubbleShape == 3 || bubbleShape == 2)
color: sentByMe ? MPalette.background : eventType === "notice" ? MPalette.primary : MPalette.accent
radius: 2
}
Component {
id: openFolderDialog
Rectangle {
anchors.top: parent.top
anchors.right: parent.right
OpenFolderDialog {}
width: parent.width / 2
height: parent.height / 2
visible: sentByMe && (bubbleShape == 3 || bubbleShape == 2)
color: sentByMe ? MPalette.background : eventType === "notice" ? MPalette.primary : MPalette.accent
radius: 2
}
Component {
id: fileDelegateContextMenu
Rectangle {
anchors.bottom: parent.bottom
anchors.left: parent.left
FileDelegateContextMenu {}
width: parent.width / 2
height: parent.height / 2
visible: !sentByMe && (bubbleShape == 1 || bubbleShape == 2)
color: sentByMe ? MPalette.background : eventType === "notice" ? MPalette.primary : MPalette.accent
radius: 2
}
Rectangle {
anchors.bottom: parent.bottom
anchors.right: parent.right
width: parent.width / 2
height: parent.height / 2
visible: sentByMe && (bubbleShape == 1 || bubbleShape == 2)
color: sentByMe ? MPalette.background : eventType === "notice" ? MPalette.primary : MPalette.accent
radius: 2
}
AutoMouseArea {
anchors.fill: parent
id: messageMouseArea
onSecondaryClicked: {
var contextMenu = fileDelegateContextMenu.createObject(ApplicationWindow.overlay)
contextMenu.viewSource.connect(function() {
messageSourceDialog.createObject(ApplicationWindow.overlay, {"sourceText": toolTip}).open()
})
contextMenu.downloadAndOpen.connect(downloadAndOpen)
contextMenu.saveFileAs.connect(saveFileAs)
contextMenu.reply.connect(function() {
roomPanelInput.replyUser = author
roomPanelInput.replyEventID = eventId
roomPanelInput.replyContent = message
roomPanelInput.isReply = true
roomPanelInput.focus()
})
contextMenu.redact.connect(function() {
currentRoom.redactEvent(eventId)
})
contextMenu.popup()
}
Component {
id: messageSourceDialog
MessageSourceDialog {}
}
Component {
id: openFolderDialog
OpenFolderDialog {}
}
Component {
id: fileDelegateContextMenu
FileDelegateContextMenu {}
}
}
}
}
@ -225,6 +246,7 @@ RowLayout {
if (Qt.openUrlExternally(progressInfo.localDir)) return;
}
function humanSize(bytes)
{
if (!bytes)

View File

@ -35,8 +35,8 @@ RowLayout {
}
Avatar {
Layout.preferredWidth: 36
Layout.preferredHeight: 36
Layout.preferredWidth: 32
Layout.preferredHeight: 32
Layout.alignment: Qt.AlignBottom
visible: avatarVisible
@ -59,8 +59,8 @@ RowLayout {
}
Label {
Layout.preferredWidth: 36
Layout.preferredHeight: 36
Layout.preferredWidth: 32
Layout.preferredHeight: 32
visible: !(sentByMe || avatarVisible)
}
@ -73,7 +73,7 @@ RowLayout {
}
Image {
Layout.maximumWidth: messageListView.width - (!sentByMe ? 36 + root.spacing : 0) - 48
Layout.maximumWidth: messageListView.width - (!sentByMe ? 32 + root.spacing : 0) - 48
id: img

View File

@ -34,8 +34,8 @@ ColumnLayout {
spacing: 4
Avatar {
Layout.preferredWidth: 36
Layout.preferredHeight: 36
Layout.preferredWidth: 32
Layout.preferredHeight: 32
Layout.alignment: Qt.AlignBottom
visible: avatarVisible
@ -58,14 +58,14 @@ ColumnLayout {
}
Item {
Layout.preferredWidth: 36
Layout.preferredHeight: 36
Layout.preferredWidth: 32
Layout.preferredHeight: 32
visible: !(sentByMe || avatarVisible)
}
Control {
Layout.maximumWidth: messageListView.width - (!sentByMe ? 36 + messageRow.spacing : 0) - 48
Layout.maximumWidth: messageListView.width - (!sentByMe ? 32 + messageRow.spacing : 0) - 48
verticalPadding: 8
horizontalPadding: 16
@ -259,7 +259,7 @@ ColumnLayout {
RowLayout {
Layout.alignment: sentByMe ? Qt.AlignRight : Qt.AlignLeft
Layout.leftMargin: sentByMe ? undefined : 36 + messageRow.spacing + 12
Layout.leftMargin: sentByMe ? undefined : 32 + messageRow.spacing + 12
Layout.rightMargin: sentByMe ? 12 : undefined
Layout.bottomMargin: 4

View File

@ -1,251 +0,0 @@
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import QtQuick.Controls.Material 2.12
import QtGraphicalEffects 1.0
import QtMultimedia 5.12
import Qt.labs.platform 1.0 as Platform
import Spectral 0.1
import Spectral.Setting 0.1
import Spectral.Component 2.0
import Spectral.Dialog 2.0
import Spectral.Menu.Timeline 2.0
import Spectral.Effect 2.0
import Spectral.Font 0.1
RowLayout {
readonly property bool avatarVisible: showAuthor && !sentByMe
readonly property bool sentByMe: author === currentRoom.localUser
property bool openOnFinished: false
property bool playOnFinished: false
readonly property bool downloaded: progressInfo && progressInfo.completed
id: root
spacing: 4
z: -5
onDownloadedChanged: {
if (downloaded && openOnFinished) {
openSavedFile()
openOnFinished = false
}
if (downloaded && playOnFinished) {
playSavedFile()
playOnFinished = false
}
}
Avatar {
Layout.preferredWidth: 36
Layout.preferredHeight: 36
Layout.alignment: Qt.AlignBottom
visible: avatarVisible
hint: author.displayName
source: author.avatarMediaId
Component {
id: userDetailDialog
UserDetailDialog {}
}
RippleEffect {
anchors.fill: parent
circular: true
onClicked: userDetailDialog.createObject(ApplicationWindow.overlay, {"room": currentRoom, "user": author}).open()
}
}
Label {
Layout.preferredWidth: 36
Layout.preferredHeight: 36
visible: !(sentByMe || avatarVisible)
}
Video {
Layout.fillWidth: true
Layout.preferredHeight: width
id: vid
source: progressInfo.localPath
loops: MediaPlayer.Infinite
autoPlay: true
fillMode: VideoOutput.PreserveAspectFit
layer.enabled: true
layer.effect: OpacityMask {
maskSource: Rectangle {
width: vid.width
height: vid.height
radius: 18
}
}
Label {
anchors.centerIn: parent
visible: vid.playbackState != MediaPlayer.PlayingState
color: "white"
text: "Video"
font.pixelSize: 16
padding: 8
background: Rectangle {
radius: height / 2
color: "black"
opacity: 0.3
}
}
Control {
anchors.bottom: parent.bottom
anchors.bottomMargin: 8
anchors.right: parent.right
anchors.rightMargin: 8
horizontalPadding: 8
verticalPadding: 4
contentItem: RowLayout {
Label {
text: Qt.formatTime(time, "hh:mm AP")
color: "white"
font.pixelSize: 12
}
Label {
text: author.displayName
color: "white"
font.pixelSize: 12
}
}
background: Rectangle {
radius: height / 2
color: "black"
opacity: 0.3
}
}
Rectangle {
anchors.fill: parent
visible: progressInfo.active && !downloaded
color: "#BB000000"
ProgressBar {
anchors.centerIn: parent
width: parent.width * 0.8
from: 0
to: progressInfo.total
value: progressInfo.progress
}
}
RippleEffect {
anchors.fill: parent
id: messageMouseArea
onPrimaryClicked: downloadAndPlay()
onSecondaryClicked: {
var contextMenu = imageDelegateContextMenu.createObject(ApplicationWindow.overlay)
contextMenu.viewSource.connect(function() {
messageSourceDialog.createObject(ApplicationWindow.overlay, {"sourceText": toolTip}).open()
})
contextMenu.downloadAndOpen.connect(downloadAndOpen)
contextMenu.saveFileAs.connect(saveFileAs)
contextMenu.reply.connect(function() {
roomPanelInput.replyUser = author
roomPanelInput.replyEventID = eventId
roomPanelInput.replyContent = message
roomPanelInput.isReply = true
roomPanelInput.focus()
})
contextMenu.redact.connect(function() {
currentRoom.redactEvent(eventId)
})
contextMenu.popup()
}
Component {
id: messageSourceDialog
MessageSourceDialog {}
}
Component {
id: openFolderDialog
OpenFolderDialog {}
}
Component {
id: imageDelegateContextMenu
FileDelegateContextMenu {}
}
}
}
function saveFileAs() {
var folderDialog = openFolderDialog.createObject(ApplicationWindow.overlay)
folderDialog.chosen.connect(function(path) {
if (!path) return
currentRoom.downloadFile(eventId, path + "/" + currentRoom.fileNameToDownload(eventId))
})
folderDialog.open()
}
function downloadAndOpen()
{
if (downloaded) openSavedFile()
else
{
openOnFinished = true
currentRoom.downloadFile(eventId, Platform.StandardPaths.writableLocation(Platform.StandardPaths.CacheLocation) + "/" + eventId.replace(":", "_").replace("/", "_").replace("+", "_") + currentRoom.fileNameToDownload(eventId))
}
}
function downloadAndPlay()
{
if (downloaded) playSavedFile()
else
{
playOnFinished = true
currentRoom.downloadFile(eventId, Platform.StandardPaths.writableLocation(Platform.StandardPaths.CacheLocation) + "/" + eventId.replace(":", "_").replace("/", "_").replace("+", "_") + currentRoom.fileNameToDownload(eventId))
}
}
function openSavedFile()
{
if (Qt.openUrlExternally(progressInfo.localPath)) return;
if (Qt.openUrlExternally(progressInfo.localDir)) return;
}
function playSavedFile()
{
vid.stop()
vid.play()
}
}

View File

@ -4,4 +4,3 @@ StateDelegate 2.0 StateDelegate.qml
SectionDelegate 2.0 SectionDelegate.qml
ImageDelegate 2.0 ImageDelegate.qml
FileDelegate 2.0 FileDelegate.qml
VideoDelegate 2.0 VideoDelegate.qml

View File

@ -219,24 +219,6 @@ Item {
}
}
DelegateChoice {
roleValue: "video"
delegate: ColumnLayout {
width: messageListView.width
SectionDelegate {
Layout.alignment: Qt.AlignHCenter
Layout.maximumWidth: parent.width
visible: showSection
}
VideoDelegate {
Layout.alignment: sentByMe ? Qt.AlignRight : Qt.AlignLeft
}
}
}
DelegateChoice {
roleValue: "file"
delegate: ColumnLayout {

View File

@ -57,6 +57,5 @@
<file>imports/Spectral/Dialog/AccountDetailDialog.qml</file>
<file>imports/Spectral/Dialog/OpenFileDialog.qml</file>
<file>imports/Spectral/Dialog/OpenFolderDialog.qml</file>
<file>imports/Spectral/Component/Timeline/VideoDelegate.qml</file>
</qresource>
</RCC>

View File

@ -289,8 +289,6 @@ QVariant MessageEventModel::data(const QModelIndex& idx, int role) const {
return "image";
case MessageEventType::Audio:
return "audio";
case MessageEventType::Video:
return "video";
}
if (e->hasFileContent())
return "file";