Compare commits

..

5 Commits

Author SHA1 Message Date
expectocode 117bfb4790 squarify files 2019-05-11 17:01:06 +01:00
expectocode 1018920ec3 Merge branch 'develop' into square-messages 2019-05-11 16:58:54 +01:00
Black Hat cab82d7b8a Add VideoDelegate. 2019-05-11 22:12:58 +08:00
Black Hat 2cddd4face Clean up FileDelegate. 2019-05-11 21:32:40 +08:00
Black Hat 5700c967ae Resize avatar in timeline. 2019-05-11 21:03:44 +08:00
8 changed files with 426 additions and 175 deletions

View File

@ -14,7 +14,7 @@ import Spectral.Menu.Timeline 2.0
import Spectral.Font 0.1 import Spectral.Font 0.1
import Spectral.Effect 2.0 import Spectral.Effect 2.0
ColumnLayout { RowLayout {
readonly property bool avatarVisible: !sentByMe && showAuthor readonly property bool avatarVisible: !sentByMe && showAuthor
readonly property bool sentByMe: author === currentRoom.localUser readonly property bool sentByMe: author === currentRoom.localUser
@ -23,32 +23,16 @@ ColumnLayout {
id: root id: root
spacing: 0 spacing: 4
onDownloadedChanged: if (downloaded && openOnFinished) openSavedFile() onDownloadedChanged: if (downloaded && openOnFinished) openSavedFile()
Label {
Layout.leftMargin: 48
text: author.displayName
visible: avatarVisible
font.pixelSize: 13
verticalAlignment: Text.AlignVCenter
}
RowLayout {
z: -5 z: -5
id: messageRow
spacing: 4
Avatar { Avatar {
Layout.preferredWidth: 32 Layout.preferredWidth: 36
Layout.preferredHeight: 32 Layout.preferredHeight: 36
Layout.alignment: Qt.AlignTop Layout.alignment: Qt.AlignBottom
visible: avatarVisible visible: avatarVisible
hint: author.displayName hint: author.displayName
@ -70,22 +54,14 @@ ColumnLayout {
} }
Label { Label {
Layout.preferredWidth: 32 Layout.preferredWidth: 36
Layout.preferredHeight: 32 Layout.preferredHeight: 36
Layout.alignment: Qt.AlignTop
visible: !(sentByMe || avatarVisible) visible: !(sentByMe || avatarVisible)
text: Qt.formatTime(time, "hh:mm AP")
color: "#5B7480"
font.pixelSize: 10
horizontalAlignment: Label.AlignHCenter
verticalAlignment: Label.AlignVCenter
} }
Control { Control {
Layout.maximumWidth: messageListView.width - (!sentByMe ? 32 + messageRow.spacing : 0) - 48 Layout.maximumWidth: messageListView.width - (!sentByMe ? 36 + root.spacing : 0) - 48
padding: 12 padding: 12
@ -100,17 +76,21 @@ ColumnLayout {
ColumnLayout { ColumnLayout {
Label { Label {
Layout.alignment: Qt.AlignVCenter Layout.fillWidth: true
text: display text: display
wrapMode: Label.Wrap
font.pixelSize: 18 font.pixelSize: 18
font.weight: Font.Medium font.weight: Font.Medium
font.capitalization: Font.AllUppercase font.capitalization: Font.AllUppercase
} }
Label { Label {
Layout.fillWidth: true
text: progressInfo.active ? (humanSize(progressInfo.progress) + "/" + humanSize(progressInfo.total)) : humanSize(content.info ? content.info.size : 0) text: progressInfo.active ? (humanSize(progressInfo.progress) + "/" + humanSize(progressInfo.total)) : humanSize(content.info ? content.info.size : 0)
color: MPalette.lighter color: MPalette.lighter
wrapMode: Label.Wrap
} }
} }
} }
@ -126,10 +106,10 @@ ColumnLayout {
width: parent.width / 2 width: parent.width / 2
height: parent.height / 2 height: parent.height / 2
visible: !sentByMe && (bubbleShape == 3 || bubbleShape == 2) visible: true
color: sentByMe ? MPalette.background : eventType === "notice" ? MPalette.primary : MPalette.accent color: sentByMe ? MPalette.background : eventType === "notice" ? MPalette.primary : MPalette.accent
radius: 2 radius: 5
} }
Rectangle { Rectangle {
@ -139,10 +119,10 @@ ColumnLayout {
width: parent.width / 2 width: parent.width / 2
height: parent.height / 2 height: parent.height / 2
visible: sentByMe && (bubbleShape == 3 || bubbleShape == 2) visible: true
color: sentByMe ? MPalette.background : eventType === "notice" ? MPalette.primary : MPalette.accent color: sentByMe ? MPalette.background : eventType === "notice" ? MPalette.primary : MPalette.accent
radius: 2 radius: 5
} }
Rectangle { Rectangle {
@ -152,10 +132,10 @@ ColumnLayout {
width: parent.width / 2 width: parent.width / 2
height: parent.height / 2 height: parent.height / 2
visible: !sentByMe && (bubbleShape == 1 || bubbleShape == 2) visible: true
color: sentByMe ? MPalette.background : eventType === "notice" ? MPalette.primary : MPalette.accent color: sentByMe ? MPalette.background : eventType === "notice" ? MPalette.primary : MPalette.accent
radius: 2 radius: 5
} }
Rectangle { Rectangle {
@ -165,10 +145,10 @@ ColumnLayout {
width: parent.width / 2 width: parent.width / 2
height: parent.height / 2 height: parent.height / 2
visible: sentByMe && (bubbleShape == 1 || bubbleShape == 2) visible: true
color: sentByMe ? MPalette.background : eventType === "notice" ? MPalette.primary : MPalette.accent color: sentByMe ? MPalette.background : eventType === "notice" ? MPalette.primary : MPalette.accent
radius: 2 radius: 5
} }
AutoMouseArea { AutoMouseArea {
@ -216,7 +196,6 @@ ColumnLayout {
} }
} }
} }
}
function saveFileAs() { function saveFileAs() {
var folderDialog = openFolderDialog.createObject(ApplicationWindow.overlay) var folderDialog = openFolderDialog.createObject(ApplicationWindow.overlay)
@ -246,7 +225,6 @@ ColumnLayout {
if (Qt.openUrlExternally(progressInfo.localDir)) return; if (Qt.openUrlExternally(progressInfo.localDir)) return;
} }
function humanSize(bytes) function humanSize(bytes)
{ {
if (!bytes) if (!bytes)

View File

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

View File

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

View File

@ -0,0 +1,251 @@
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,3 +4,4 @@ StateDelegate 2.0 StateDelegate.qml
SectionDelegate 2.0 SectionDelegate.qml SectionDelegate 2.0 SectionDelegate.qml
ImageDelegate 2.0 ImageDelegate.qml ImageDelegate 2.0 ImageDelegate.qml
FileDelegate 2.0 FileDelegate.qml FileDelegate 2.0 FileDelegate.qml
VideoDelegate 2.0 VideoDelegate.qml

View File

@ -219,6 +219,24 @@ 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 { DelegateChoice {
roleValue: "file" roleValue: "file"
delegate: ColumnLayout { delegate: ColumnLayout {

View File

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

View File

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