diff --git a/src/qml/messages/AttachmentMessageAudio.qml b/src/qml/messages/AttachmentMessageAudio.qml index cad40b65..8844e893 100644 --- a/src/qml/messages/AttachmentMessageAudio.qml +++ b/src/qml/messages/AttachmentMessageAudio.qml @@ -1,161 +1,151 @@ /* Copyright (c) 2017-2018 Montel Laurent This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License or ( at your option ) version 3 or, at the discretion of KDE e.V. ( which shall act as a proxy as in section 14 of the GPLv3 ), any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.9 import QtMultimedia 5.8 import QtQuick.Controls 2.2 as QQC2 import org.kde.kirigami 2.1 as Kirigami import QtQuick.Layouts 1.1 import KDE.Ruqola.DebugCategory 1.0 import "../js/convert.js" as ConvertScript; import "../common" MessageBase { id: attachmentAudio RowLayout { AvatarImage { id: avatarRect avatarurl: i_avatar aliasname: i_aliasname username: i_username } + Repeater { id: repearterAttachments model: i_attachments MediaPlayer { id: audioPlayer autoPlay: false onPaused: { playerButton.source = "media-playback-start" } onPlaying: { playerButton.source = "media-playback-pause" } onStopped: { playerButton.source = "media-playback-start" playerSlider.value=0 } onPositionChanged: { playerSlider.sync = true playerSlider.value = audioPlayer.position / audioPlayer.duration playerSlider.sync = false timeLabel.text = ConvertScript.convertTimeString(audioPlayer.position) + "/" + ConvertScript.convertTimeString(audioPlayer.duration) } source: rcAccount.attachmentUrl(model.modelData.link) } ColumnLayout { Layout.fillWidth: true QQC2.Label { //TODO remove duplicate code text: model.modelData.title === "" ? "" : i18n("File Uploaded: %1", model.modelData.title) visible: model.modelData.title !== "" wrapMode: QQC2.Label.Wrap anchors.leftMargin: Kirigami.Units.smallSpacing anchors.rightMargin: Kirigami.Units.smallSpacing } RowLayout { Kirigami.Icon { id: playerButton source: "media-playback-start" width: 24 height: 24 MouseArea { anchors.fill: parent onClicked: { console.log(RuqolaDebugCategorySingleton.category, "Click on download audio file"); if (repearterAttachments.audioPlayer.source !== "") { if (repearterAttachments.audioPlayer.playbackState === MediaPlayer.PlayingState) { repearterAttachments.audioPlayer.pause() } else { repearterAttachments.audioPlayer.play() } } else { console.log(RuqolaDebugCategorySingleton.category, "Audio file no found"); } } } } QQC2.Slider { id: playerSlider Layout.fillWidth: true property bool sync: false onValueChanged: { if (!sync) { audioPlayer.seek(value * audioPlayer.duration) } } } QQC2.Label { id: timeLabel text: "00:00/00:00" } DownloadButton { id: download onDownloadButtonClicked: { //TODO messageMain.downloadAttachment(model.modelData.link) } } } QQC2.Label { text: model.modelData.description visible: model.modelData.description !== "" wrapMode: QQC2.Label.Wrap anchors.leftMargin: Kirigami.Units.smallSpacing anchors.rightMargin: Kirigami.Units.smallSpacing } } } - Repeater { + RepeaterReactions { id: repearterReactions model: i_reactions - Row { - QQC2.Label { - id: numberOfReact - renderType: Text.NativeRendering - textFormat: Text.RichText - text: model.modelData.convertedReactionName - wrapMode: QQC2.Label.Wrap - anchors.leftMargin: Kirigami.Units.smallSpacing - anchors.rightMargin: Kirigami.Units.smallSpacing - } - } } TimestampText { id: timestampText timestamp: i_timestamp } } } diff --git a/src/qml/messages/AttachmentMessageImage.qml b/src/qml/messages/AttachmentMessageImage.qml index bb92171d..0051e1b4 100644 --- a/src/qml/messages/AttachmentMessageImage.qml +++ b/src/qml/messages/AttachmentMessageImage.qml @@ -1,204 +1,193 @@ /* Copyright (c) 2017-2018 Montel Laurent This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License or ( at your option ) version 3 or, at the discretion of KDE e.V. ( which shall act as a proxy as in section 14 of the GPLv3 ), any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.9 import QtQuick.Controls 2.2 as QQC2 import org.kde.kirigami 2.1 as Kirigami import KDE.Ruqola.DebugCategory 1.0 import QtQuick.Layouts 1.1 import "../common" MessageBase { id: messageMain MessageMenu { id: menu can_editing_message: i_can_editing_message starred: i_starred } RowLayout { AvatarImage { id: avatarRect avatarurl: i_avatar aliasname: i_aliasname username: i_username } Repeater { id: repearterAttachments model: i_attachments Row { Column { QQC2.Label { - id: imageTitle + id: imageTitle text: model.modelData.title === "" ? "" : model.modelData.imageTitle visible: model.modelData.title !== "" wrapMode: QQC2.Label.Wrap anchors.leftMargin: Kirigami.Units.smallSpacing anchors.rightMargin: Kirigami.Units.smallSpacing renderType: Text.NativeRendering textFormat: Text.RichText onLinkActivated: { messageMain.displayImage(imageUrl.source, model.modelData.title, model.modelData.isAnimatedImage) } MouseArea { anchors.fill: parent acceptedButtons: Qt.RightButton onClicked: { if (mouse.button === Qt.RightButton) { menu.x = mouse.x menu.y = mouse.y menu.open(); } } } } Image { id: imageUrl visible: model.modelData.isAnimatedImage readonly property int imageHeight: model.modelData.imageHeight === -1 ? 200 : model.modelData.imageHeight source: rcAccount.attachmentUrl(model.modelData.link) asynchronous: true fillMode: Image.PreserveAspectFit //TODO customize it. width: model.modelData.imageWidth === -1 ? 200 : model.modelData.imageWidth height: 0 sourceSize.width: 200 sourceSize.height: 200 onStatusChanged: { if(status == Image.Error){ console.log(RuqolaDebugCategorySingleton.category, "Image load error! Trying to reload. " + source) } } MouseArea { anchors.fill: parent onClicked: { if(status === Image.Error) { console.log(RuqolaDebugCategorySingleton.category, "Image not loaded."); } else { messageMain.displayImage(imageUrl.source, imageTitle.text, model.modelData.isAnimatedImage) } } } } AnimatedImage { id: imageAnimatedUrl visible: model.modelData.isAnimatedImage readonly property int imageHeight: model.modelData.imageHeight === -1 ? 200 : model.modelData.imageHeight source: rcAccount.attachmentUrl(model.modelData.link) asynchronous: true fillMode: Image.PreserveAspectFit width: model.modelData.imageWidth === -1 ? 200 : model.modelData.imageWidth height: 0 //sourceSize.width: 200 //sourceSize.height: 200 onStatusChanged: { if(status == Image.Error){ console.log(RuqolaDebugCategorySingleton.category, "Image load error! Trying to reload. " + source) } } MouseArea { anchors.fill: parent onClicked: { if(status === Image.Error) { console.log(RuqolaDebugCategorySingleton.category, "Image not loaded."); } else { messageMain.displayImage(imageAnimatedUrl.source, imageTitle.text, model.modelData.isAnimatedImage) } } } } QQC2.Label { text: model.modelData.description wrapMode: QQC2.Label.Wrap anchors.leftMargin: Kirigami.Units.smallSpacing anchors.rightMargin: Kirigami.Units.smallSpacing visible: model.modelData.description !== "" MouseArea { anchors.fill: parent acceptedButtons: Qt.RightButton onClicked: { if (mouse.button === Qt.RightButton) { menu.x = mouse.x menu.y = mouse.y menu.open(); } } } } } ShowHideButton { targetAnimation: model.modelData.isAnimatedImage ? imageAnimatedUrl : imageUrl defaultHeight: model.modelData.isAnimatedImage ? imageAnimatedUrl.imageHeight : Url.imageHeight } DownloadButton { id: download onDownloadButtonClicked: { messageMain.downloadAttachment(model.modelData.link) } } Connections { target: rcAccount onFileDownloaded: { //console.log(RuqolaDebugCategorySingleton.category, " IMAGE SUPPORT: " + filePath + " cacheImageUrl :" + cacheImageUrl + " model.modelData.link: " + model.modelData.link) if (filePath === model.modelData.link) { console.log(RuqolaDebugCategorySingleton.category, "Image updated: " + cacheImageUrl) imageUrl.source = cacheImageUrl; imageAnimatedUrl.source = cacheImageUrl; } } } } } - Repeater { + RepeaterReactions { id: repearterReactions model: i_reactions - Row { - QQC2.Label { - id: numberOfReact - renderType: Text.NativeRendering - textFormat: Text.RichText - text: model.modelData.convertedReactionName - wrapMode: QQC2.Label.Wrap - anchors.leftMargin: Kirigami.Units.smallSpacing - anchors.rightMargin: Kirigami.Units.smallSpacing - } - } } Item { Layout.fillWidth: true } TimestampText { id: timestampText timestamp: i_timestamp } } } diff --git a/src/qml/messages/AttachmentMessageVideo.qml b/src/qml/messages/AttachmentMessageVideo.qml index d832fe74..16510711 100644 --- a/src/qml/messages/AttachmentMessageVideo.qml +++ b/src/qml/messages/AttachmentMessageVideo.qml @@ -1,177 +1,166 @@ /* Copyright (c) 2017-2018 Montel Laurent This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License or ( at your option ) version 3 or, at the discretion of KDE e.V. ( which shall act as a proxy as in section 14 of the GPLv3 ), any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.9 import QtQuick.Controls 2.2 as QQC2 import org.kde.kirigami 2.1 as Kirigami import QtMultimedia 5.8 import QtQuick.Layouts 1.1 import "../js/convert.js" as ConvertScript; import "../common" import KDE.Ruqola.DebugCategory 1.0 MessageBase { id: attachmentVideo MediaPlayer { id: videoPlayer autoPlay: false onPaused: { playerButton.source = "media-playback-start" } onPlaying: { playerButton.source = "media-playback-pause" } onStopped: { playerButton.source = "media-playback-start" playerSlider.value=0 } onPositionChanged: { playerSlider.sync = true playerSlider.value = videoPlayer.position / videoPlayer.duration playerSlider.sync = false timeLabel.text = ConvertScript.convertTimeString(videoPlayer.position) + "/" + ConvertScript.convertTimeString(videoPlayer.duration) } source: rcAccount.attachmentUrl(model.modelData.link) } RowLayout { AvatarImage { id: avatarRect avatarurl: i_avatar aliasname: i_aliasname username: i_username } Repeater { id: repearterAttachments model: i_attachments RowLayout { ColumnLayout { Layout.fillWidth: true QQC2.Label { //TODO remove duplicate code text: model.modelData.title === "" ? "" : i18n("File Uploaded: %1", model.modelData.title) visible: model.modelData.title !== "" wrapMode: QQC2.Label.Wrap anchors.leftMargin: Kirigami.Units.smallSpacing anchors.rightMargin: Kirigami.Units.smallSpacing } VideoOutput { id: videoOutput property int videoHeight: 100 Layout.fillWidth: true source: attachmentVideo.videoPlayer width: 100 height: 0 } RowLayout { //Verify position. //Add video media Kirigami.Icon { id: playerButton source: "media-playback-start" width: 24 height: 24 MouseArea { anchors.fill: parent onClicked: { console.log(RuqolaDebugCategorySingleton.category, "Click on video file!"); if (repearterAttachments.videoPlayer.source !== "") { if (repearterAttachments.videoPlayer.playbackState === MediaPlayer.PlayingState) { repearterAttachments.videoPlayer.pause() } else { repearterAttachments.videoPlayer.play() } } else { console.log(RuqolaDebugCategorySingleton.category, "Video file no found"); } } } } QQC2.Slider { id: playerSlider Layout.fillWidth: true property bool sync: false onValueChanged: { if (!sync) { videoPlayer.seek(value * videoPlayer.duration) } } } QQC2.Label { id: timeLabel text: "00:00/00:00" } DownloadButton { id: download onDownloadButtonClicked: { //TODO messageMain.downloadAttachment(model.modelData.link) } } ShowHideButton { targetAnimation: videoOutput defaultHeight: videoOutput.videoHeight } } QQC2.Label { text: model.modelData.description visible: model.modelData.description !== "" wrapMode: QQC2.Label.Wrap anchors.leftMargin: Kirigami.Units.smallSpacing anchors.rightMargin: Kirigami.Units.smallSpacing } } } } - Repeater { + RepeaterReactions { id: repearterReactions model: i_reactions - Row { - QQC2.Label { - id: numberOfReact - renderType: Text.NativeRendering - textFormat: Text.RichText - text: model.modelData.convertedReactionName - wrapMode: QQC2.Label.Wrap - anchors.leftMargin: Kirigami.Units.smallSpacing - anchors.rightMargin: Kirigami.Units.smallSpacing - } - } } TimestampText { id: timestampText timestamp: i_timestamp } } } diff --git a/src/qml/messages/RepeaterReactions.qml b/src/qml/messages/RepeaterReactions.qml new file mode 100644 index 00000000..4f406777 --- /dev/null +++ b/src/qml/messages/RepeaterReactions.qml @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2018 Laurent Montel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +import QtQuick 2.9 + +import org.kde.kirigami 2.1 as Kirigami +import QtQuick.Controls 2.2 as QQC2 +import QtQuick.Layouts 1.1 +Repeater { + id: repearterReactions + Row { + QQC2.Label { + id: numberOfReact + renderType: Text.NativeRendering + textFormat: Text.RichText + text: model.modelData.convertedReactionName + wrapMode: QQC2.Label.Wrap + anchors.leftMargin: Kirigami.Units.smallSpacing + anchors.rightMargin: Kirigami.Units.smallSpacing + } + } +} diff --git a/src/qml/messages/UserMessage.qml b/src/qml/messages/UserMessage.qml index a61f6177..9933a5e9 100644 --- a/src/qml/messages/UserMessage.qml +++ b/src/qml/messages/UserMessage.qml @@ -1,208 +1,197 @@ /* * Copyright 2016 Riccardo Iaconelli * Copyright (c) 2017-2018 Montel Laurent * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ import QtQuick 2.9 import org.kde.kirigami 2.1 as Kirigami import QtQuick.Controls 2.2 as QQC2 import QtQuick.Layouts 1.1 import KDE.Ruqola.RuqolaUtils 1.0 import KDE.Ruqola.ExtraColors 1.0 import KDE.Ruqola.DebugCategory 1.0 import "../js/message.js" as MessageScript; import "../common" MessageBase { property string i_messageID property var i_urls property var i_attachments property string i_own_username id: messageMain Layout.alignment: Qt.AlignTop MessageMenu { id: menu can_editing_message: i_can_editing_message starred: i_starred } RowLayout { AvatarImage { id: avatarRect avatarurl: i_avatar aliasname: i_aliasname username: i_username } ColumnLayout { Layout.fillHeight: true Kirigami.Heading { id: usernameLabel level: 5 Layout.alignment: Qt.AlignLeft font.bold: true text: i_aliasname + ' ' + i_usernameurl + (i_editedByUserName === "" ? "" : " " + i18n("(edited by %1)", i_editedByUserName)) height: avatarRect.height onLinkActivated: messageMain.linkActivated(link) MouseArea { anchors.fill: parent acceptedButtons: Qt.RightButton onClicked: { if (mouse.button === Qt.RightButton) { menu.x = mouse.x menu.y = mouse.y menu.open(); } } } } Column { id: fullTextColumn Layout.fillWidth: true QQC2.Label { width: parent.width id: textLabel renderType: Text.NativeRendering textFormat: Text.RichText text: i_messageText wrapMode: QQC2.Label.Wrap onLinkActivated: messageMain.linkActivated(link) MouseArea { anchors.fill: parent acceptedButtons: Qt.RightButton onClicked: { if (mouse.button === Qt.RightButton) { menu.x = mouse.x menu.y = mouse.y menu.open(); } } } } Column { id: urlColumn width: parent.width //TODO //Reactivate when we have a parsed url ! //see info about bugs // Repeater { // id: repeaterUrl // model: i_urls // Text { // //Display it only if url != text otherwise it's not necessary // visible: model.modelData.url !== i_originalMessage // width: urlColumn.width // text: model.modelData.description === "" ? // RuqolaUtils.markdownToRichText(model.modelData.url) : // RuqolaUtils.markdownToRichText(model.modelData.description) // wrapMode: QQC2.Label.Wrap // renderType: Text.NativeRendering // textFormat: Text.RichText // onLinkActivated: messageMain.linkActivated(link) // } // } - Repeater { + RepeaterReactions { id: repearterReactions model: i_reactions - Row { - QQC2.Label { - id: numberOfReact - renderType: Text.NativeRendering - textFormat: Text.RichText - text: model.modelData.convertedReactionName - wrapMode: QQC2.Label.Wrap - anchors.leftMargin: Kirigami.Units.smallSpacing - anchors.rightMargin: Kirigami.Units.smallSpacing - } - } } Repeater { id: repearterAttachments model: i_attachments Column { Text { visible: model.modelData.authorName !== "" width: urlColumn.width text: model.modelData.authorName wrapMode: QQC2.Label.Wrap anchors.leftMargin: Kirigami.Units.smallSpacing anchors.rightMargin: Kirigami.Units.smallSpacing } Row { QQC2.Label { id: attachmentTitle renderType: Text.NativeRendering textFormat: Text.RichText visible: model.modelData.title !== "" width: urlColumn.width text: model.modelData.displayTitle wrapMode: QQC2.Label.Wrap anchors.leftMargin: Kirigami.Units.smallSpacing anchors.rightMargin: Kirigami.Units.smallSpacing onLinkActivated: { messageMain.linkActivated(link) } } DownloadButton { id: downloadButton visible: model.modelData.canDownloadAttachment onDownloadButtonClicked: { messageMain.downloadAttachment(model.modelData.link) } } Item { Layout.fillWidth: true } } QQC2.Label { visible: model.modelData.description !== "" width: urlColumn.width text: model.modelData.description wrapMode: QQC2.Label.Wrap anchors.leftMargin: Kirigami.Units.smallSpacing anchors.rightMargin: Kirigami.Units.smallSpacing } } } } } } TimestampText { id: timestampText timestamp: i_timestamp } } } diff --git a/src/qml/qml.qrc b/src/qml/qml.qrc index ae3141f5..aeff3e34 100644 --- a/src/qml/qml.qrc +++ b/src/qml/qml.qrc @@ -1,72 +1,73 @@ Desktop.qml FancyMessageDelegate.qml RoomsView.qml RoomDelegate.qml Login.qml UserInput.qml LoginPage.qml ExtraColors.qml ActiveChat.qml AboutDialog.qml PersonsListView.qml LicenseDialog.qml CreateNewChannelDialog.qml OpenDirectChannelDialog.qml ChannelInfoDialog.qml DeleteMessageDialog.qml AddUserDialog.qml DeleteRoomDialog.qml TakeVideoMessageDialog.qml TextFieldEditor.qml DebugCategory.qml ConfigureServerList.qml MainComponent.qml RoomsComponent.qml ArchiveRoomDialog.qml RuqolaMenuSeparator.qml DownloadFileDialog.qml UploadFileDialog.qml DisplayImageDialog.qml EncryptedConversationDialog.qml SearchChannelDialog.qml ShowFilesInRoomDialog.qml MessageLine.qml ShowSearchMessageDialog.qml DeleteAccountDialog.qml OpenChannelDialog.qml PrivateChannelInfoDialog.qml PasswordLineEdit.qml NotificationOptionsDialog.qml LeaveChannelDialog.qml DeleteFileAttachmentDialog.qml UserInfoDialog.qml messages/SystemMessage.qml messages/UserMessage.qml messages/AttachmentMessageAudio.qml messages/AttachmentMessageImage.qml messages/AttachmentMessageVideo.qml messages/JitsiVideoMessage.qml messages/NewDateLabel.qml messages/MessageBase.qml messages/MessageMenu.qml messages/TimestampText.qml messages/ShowHideButton.qml + messages/RepeaterReactions.qml common/DownloadButton.qml common/AvatarImage.qml common/DeleteButton.qml icons/systray.png icons/attach-button.jpg js/message.js js/convert.js