diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 10d2ebf..31a8036 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,26 +1,60 @@ stages: + - preparation - build + - deploy +preparation-flatpak: + image: debian:latest + stage: preparation + before_script: + - mkdir -p tmp + - apt-get update + - apt-get install -y git + script: + - cd tmp + - git clone "https://$GIT_USERNAME:$GIT_PASSWORD@gitlab.com/b0/matrique-repo" + - cd ../ + artifacts: + paths: + - tmp/ + build-native: image: rabits/qt:5.11-desktop stage: build + cache: {} + before_script: + - git submodule update --init --recursive + script: + - mkdir -p build && cd build + - qmake ../matrique.pro -spec linux-g++ CONFIG+=qtquickcompiler + - make -j4 + +build-flatpak: + image: black0/flatpak + stage: build before_script: - git submodule update --init --recursive script: - - mkdir build && cd build - - qmake ../matrique.pro -spec linux-g++ CONFIG+=qtquickcompiler - - make -j4 - + - gpg2 -v --import <(echo "$GPG_SECRET_KEY") + - cd flatpak + - flatpak-builder --repo=../tmp/matrique-repo/public build-dir org.eu.encom.matrique.json --force-clean --gpg-sign=52986BF4D61350EC249F2E891B0DB3358FC5E4B2 + - cd ../ artifacts: paths: - - build/ - -build-flatpak: - image: fedora:latest - stage: build - before-script: dnf install flatpak + - tmp/ + +deploy-flatpak: + only: + - master + image: debian:latest + stage: deploy + before_script: + - apt-get update + - apt-get install -y git + - git config --global user.name "$GIT_NAME" + - git config --global user.email "$GIT_EMAIL" script: - - flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub - - flatpak install flathub org.kde.Platform//5.11 - - gpg2 -v --import <(echo $GPG_SECRET_KEY) - + - cd tmp/matrique-repo + - git add -A + - git commit -m "$CI_COMMIT_MESSAGE" + - git push origin master \ No newline at end of file diff --git a/include/libqmatrixclient b/include/libqmatrixclient index dc3acd3..7298e99 160000 --- a/include/libqmatrixclient +++ b/include/libqmatrixclient @@ -1 +1 @@ -Subproject commit dc3acd336e30a17d6b5d0cbe6cde2838737c9030 +Subproject commit 7298e99125522c4d010ec83052cd10ce085e09b4 diff --git a/qml/component/ImageBubble.qml b/qml/component/ImageBubble.qml index 3e480d2..9b0b4ec 100644 --- a/qml/component/ImageBubble.qml +++ b/qml/component/ImageBubble.qml @@ -28,12 +28,25 @@ AvatarContainer { anchors.fill: parent hoverEnabled: true - acceptedButtons: Qt.LeftButton | Qt.RightButton propagateComposedEvents: true ToolTip.visible: containsMouse ToolTip.text: content.body - onClicked: mouse.button & Qt.LeftButton ? downloadable.downloadAndOpen() : downloadable.saveFileAs() + onClicked: downloadable.downloadAndOpen() + onPressAndHold: messageImageMenu.popup() + } + + Menu { + id: messageImageMenu + + MenuItem { + text: "View" + onTriggered: downloadable.downloadAndOpen() + } + MenuItem { + text: "Save as..." + onTriggered: downloadable.saveFileAs() + } } } } diff --git a/qml/component/MessageDelegate.qml b/qml/component/MessageDelegate.qml index 5b58f8a..c8baba7 100644 --- a/qml/component/MessageDelegate.qml +++ b/qml/component/MessageDelegate.qml @@ -13,6 +13,8 @@ Item { readonly property bool isMessage: eventType === "message" || eventType === "notice" readonly property bool isFile: eventType === "video" || eventType === "audio" || eventType === "file" || eventType === "image" + visible: eventType != "redaction" + z: -5 width: delegateLoader.width height: delegateLoader.height @@ -23,6 +25,6 @@ Item { Loader { id: delegateLoader - source: isMessage ? "MessageBubble.qml" : isState ? "StateBubble.qml" : isFile ? eventType === "image" ? "ImageBubble.qml" : "FileBubble.qml" : "" + source: eventType != "redaction" ? isMessage ? "MessageBubble.qml" : isState ? "StateBubble.qml" : isFile ? eventType === "image" ? "ImageBubble.qml" : "FileBubble.qml" : "" : "" } } diff --git a/qml/form/RoomForm.qml b/qml/form/RoomForm.qml index a694a41..bd54d24 100644 --- a/qml/form/RoomForm.qml +++ b/qml/form/RoomForm.qml @@ -230,12 +230,12 @@ Item { if (text.indexOf(PREFIX_ME) === 0) { text = text.substr(PREFIX_ME.length) - currentRoom.postMessage("m.emote", text) + matriqueController.postMessage(currentRoom, "m.emote", text) return } if (text.indexOf(PREFIX_NOTICE) === 0) { text = text.substr(PREFIX_NOTICE.length) - currentRoom.postMessage("m.notice", text) + matriqueController.postMessage(currentRoom, "m.notice", text) return } if (text.indexOf(PREFIX_RAINBOW) === 0) { @@ -246,7 +246,7 @@ Item { for (var i = 0; i < text.length; i++) { parsedText = parsedText + "" + text.charAt(i) + "" } - currentRoom.postHtmlMessage(text, parsedText, "m.text") + currentRoom.postHtmlMessage(text, parsedText) return } if (text.indexOf(PREFIX_HTML) === 0) { @@ -259,11 +259,11 @@ Item { if (text.indexOf(PREFIX_MARKDOWN) === 0) { text = text.substr(PREFIX_MARKDOWN.length) var parsedText = Markdown.markdown_parser(text) - currentRoom.postHtmlMessage(text, parsedText, "m.text") + currentRoom.postHtmlMessage(text, parsedText) return } - currentRoom.postMessage("m.text", text) + matriqueController.postMessage(currentRoom, "m.text", text) } } diff --git a/src/controller.cpp b/src/controller.cpp index 2c6e4e7..613d632 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -73,10 +73,16 @@ void Controller::reconnect() { m_connection->connectWithToken(userID, token, ""); } +void Controller::postMessage(Room* room, const QString& type, + const QString& text) { + room->postMessage("m.room.message", + QJsonObject{{"msgtype", type}, {"body", text}}); +} + void Controller::postFile(Room* room, const QUrl& localFile, const QUrl& mxcUrl) { const QString mime = getMIME(localFile); - const QString fileName = localFile.toLocalFile(); + const QString fileName = localFile.fileName(); QString msgType = "m.file"; if (mime.startsWith("image")) msgType = "m.image"; if (mime.startsWith("video")) msgType = "m.video"; diff --git a/src/controller.h b/src/controller.h index 563c010..fbdfae1 100644 --- a/src/controller.h +++ b/src/controller.h @@ -95,6 +95,7 @@ class Controller : public QObject { void errorOccured(); public slots: + void postMessage(Room* room, const QString& type, const QString& text); void postFile(Room* room, const QUrl& localFile, const QUrl& mxcUrl); QString getMIME(const QUrl& fileUrl) const; void forgetRoom(const QString& roomID); diff --git a/src/main.cpp b/src/main.cpp index 08034c3..0021fb8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -22,7 +22,6 @@ int main(int argc, char *argv[]) { QApplication app(argc, argv); qRegisterMetaType("Room*"); - qRegisterMetaType("User*"); qmlRegisterType("Matrique", 0, 1, "Controller"); diff --git a/src/messageeventmodel.cpp b/src/messageeventmodel.cpp index a1b9149..8316cd0 100644 --- a/src/messageeventmodel.cpp +++ b/src/messageeventmodel.cpp @@ -4,17 +4,35 @@ #include #include // for qmlRegisterType() -#include "events/redactionevent.h" -#include "events/roomavatarevent.h" -#include "events/roommemberevent.h" -#include "events/simplestateevents.h" +#include +#include +#include +#include +#include +#include +#include -#include "connection.h" -#include "settings.h" -#include "user.h" +QHash MessageEventModel::roleNames() const { + QHash roles = QAbstractItemModel::roleNames(); + roles[EventTypeRole] = "eventType"; + roles[EventIdRole] = "eventId"; + roles[TimeRole] = "time"; + roles[AboveTimeRole] = "aboveTime"; + roles[SectionRole] = "section"; + roles[AboveSectionRole] = "aboveSection"; + roles[AuthorRole] = "author"; + roles[AboveAuthorRole] = "aboveAuthor"; + roles[ContentRole] = "content"; + roles[ContentTypeRole] = "contentType"; + roles[ReadMarkerRole] = "readMarker"; + roles[SpecialMarksRole] = "marks"; + roles[LongOperationRole] = "progressInfo"; + roles[EventResolvedTypeRole] = "eventResolvedType"; + return roles; +} MessageEventModel::MessageEventModel(QObject* parent) - : QAbstractListModel(parent) { + : QAbstractListModel(parent), m_currentRoom(nullptr) { qmlRegisterType(); qRegisterMetaType(); } @@ -122,7 +140,7 @@ inline bool hasValidTimestamp(const QMatrixClient::TimelineItem& ti) { } QDateTime MessageEventModel::makeMessageTimestamp( - QMatrixClient::Room::rev_iter_t baseIt) const { + const QMatrixClient::Room::rev_iter_t& baseIt) const { const auto& timeline = m_currentRoom->messageEvents(); auto ts = baseIt->event()->timestamp(); if (ts.isValid()) return ts; @@ -143,7 +161,7 @@ QDateTime MessageEventModel::makeMessageTimestamp( } QString MessageEventModel::makeDateString( - QMatrixClient::Room::rev_iter_t baseIt) const { + const QMatrixClient::Room::rev_iter_t& baseIt) const { auto date = makeMessageTimestamp(baseIt).toLocalTime().date(); if (QMatrixClient::SettingsGroup("UI") .value("banner_human_friendly_date", true) @@ -344,8 +362,6 @@ QVariant MessageEventModel::data(const QModelIndex& index, int role) const { }; } - // HighlightRole is missing. This will be fixed soon. - if (role == ReadMarkerRole) return evt.id() == lastReadEventId; if (role == SpecialMarksRole) { @@ -393,23 +409,3 @@ QVariant MessageEventModel::data(const QModelIndex& index, int role) const { return QVariant(); } - -QHash MessageEventModel::roleNames() const { - QHash roles = QAbstractItemModel::roleNames(); - roles[EventTypeRole] = "eventType"; - roles[EventIdRole] = "eventId"; - roles[TimeRole] = "time"; - roles[AboveTimeRole] = "aboveTime"; - roles[SectionRole] = "section"; - roles[AboveSectionRole] = "aboveSection"; - roles[AuthorRole] = "author"; - roles[AboveAuthorRole] = "aboveAuthor"; - roles[ContentRole] = "content"; - roles[ContentTypeRole] = "contentType"; - roles[HighlightRole] = "highlight"; - roles[ReadMarkerRole] = "readMarker"; - roles[SpecialMarksRole] = "marks"; - roles[LongOperationRole] = "progressInfo"; - roles[EventResolvedTypeRole] = "eventResolvedType"; - return roles; -} diff --git a/src/messageeventmodel.h b/src/messageeventmodel.h index 8351723..1e83fb4 100644 --- a/src/messageeventmodel.h +++ b/src/messageeventmodel.h @@ -49,8 +49,9 @@ class MessageEventModel : public QAbstractListModel { bool mergingEcho = 0; int nextNewerRow = -1; - QDateTime makeMessageTimestamp(QMatrixClient::Room::rev_iter_t baseIt) const; - QString makeDateString(QMatrixClient::Room::rev_iter_t baseIt) const; + QDateTime makeMessageTimestamp( + const QMatrixClient::Room::rev_iter_t& baseIt) const; + QString makeDateString(const QMatrixClient::Room::rev_iter_t& baseIt) const; void refreshEventRoles(const int row, const QVector& roles); void refreshEventRoles(const QString& eventId, const QVector& roles);