diff --git a/qml/Setting.qml b/qml/Setting.qml index 82cca7d..85d4486 100644 --- a/qml/Setting.qml +++ b/qml/Setting.qml @@ -8,6 +8,8 @@ import "form" Page { property alias lazyLoad: generalForm.lazyLoad + property alias asyncMessageDelegate: generalForm.asyncMessageDelegate + property alias darkTheme: appearanceForm.darkTheme property alias miniMode: appearanceForm.miniMode diff --git a/qml/component/DownloadDialog.qml b/qml/component/DownloadDialog.qml deleted file mode 100644 index 1c43709..0000000 --- a/qml/component/DownloadDialog.qml +++ /dev/null @@ -1,13 +0,0 @@ -import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Dialogs 1.2 - -FileDialog { - id: locationDialog - title: "Please choose a location" - folder: shortcuts.home - selectFolder: true - - onAccepted: currentRoom.downloadFile(eventId, folder + "/" + currentRoom.fileNameToDownload(eventId)) - onVisibleChanged: visible ? {} : locationDialog.destroy() -} diff --git a/qml/component/DownloadableContent.qml b/qml/component/DownloadableContent.qml index 0268b8f..efe43f4 100644 --- a/qml/component/DownloadableContent.qml +++ b/qml/component/DownloadableContent.qml @@ -17,7 +17,7 @@ Item { onDownloadedChanged: downloaded && openOnFinished ? openSavedFile() : {} function saveFileAs() { - Qt.createComponent("DownloadDialog.qml").createObject(this).open() + matriqueController.saveFileAs(currentRoom, eventId) } function downloadAndOpen() diff --git a/qml/component/MessageDelegate.qml b/qml/component/MessageDelegate.qml index 33cef39..65b37ef 100644 --- a/qml/component/MessageDelegate.qml +++ b/qml/component/MessageDelegate.qml @@ -4,7 +4,7 @@ import QtQuick.Controls.Material 2.2 import Matrique 0.1 Item { - id: messageDelegate + readonly property bool hidden: marks === EventStatus.Redacted || marks === EventStatus.Hidden readonly property bool darkTheme: Material.theme == Material.Dark readonly property color background: darkTheme ? "#242424" : "lightgrey" @@ -12,7 +12,7 @@ Item { readonly property bool sentByMe: author === currentRoom.localUser readonly property bool isState: eventType === "state" || eventType === "emote" - visible: marks !== EventStatus.Hidden + id: messageDelegate z: -5 width: delegateLoader.width @@ -29,8 +29,10 @@ Item { Loader { id: delegateLoader + asynchronous: setting.asyncMessageDelegate + source: { - if (eventType == "redaction") return "" + if (eventType == "redaction" || hidden) return "" switch (eventType) { case "state": case "emote": diff --git a/qml/form/RoomForm.qml b/qml/form/RoomForm.qml index 8c10933..63df1c4 100644 --- a/qml/form/RoomForm.qml +++ b/qml/form/RoomForm.qml @@ -191,12 +191,15 @@ Item { } delegate: Column { + readonly property bool hidden: marks === EventStatus.Redacted || marks === EventStatus.Hidden + width: parent.width + height: hidden ? -8 : undefined spacing: 8 RowLayout { width: parent.width * 0.8 - visible: section !== aboveSection + visible: section !== aboveSection && !hidden anchors.horizontalCenter: parent.horizontalCenter spacing: 8 @@ -300,30 +303,19 @@ Item { contentItem: MaterialIcon { icon: "\ue226" } - onClicked: fileDialog.visible = true - - FileDialog { - id: fileDialog - title: "Please choose a file" - folder: shortcuts.home - selectMultiple: false - onAccepted: { - currentRoom.uploadFile(fileUrl, fileUrl, matriqueController.getMIME(fileUrl)) - var fileTransferProgressCallback = function(id, sent, total) { - if (id == fileUrl) { inputField.progress = sent / total } - } - var completedCallback = function(id, localFile, mxcUrl) { - if (id == fileUrl) { - matriqueController.postFile(currentRoom, localFile, mxcUrl) - inputField.progress = 0 - currentRoom.fileTransferCompleted.disconnect(fileTransferProgressCallback) - currentRoom.fileTransferCompleted.disconnect(completedCallback) - } - } - - currentRoom.fileTransferProgress.connect(fileTransferProgressCallback) - currentRoom.fileTransferCompleted.connect(completedCallback) + onClicked: { + var fileTransferProgressCallback = function(id, sent, total) { + inputField.progress = sent / total } + var completedCallback = function(id, localFile, mxcUrl) { + inputField.progress = 0 + currentRoom.fileTransferCompleted.disconnect(fileTransferProgressCallback) + currentRoom.fileTransferCompleted.disconnect(completedCallback) + } + + currentRoom.fileTransferProgress.connect(fileTransferProgressCallback) + currentRoom.fileTransferCompleted.connect(completedCallback) + matriqueController.uploadFile(currentRoom) } } diff --git a/qml/form/SettingForm.qml b/qml/form/SettingForm.qml deleted file mode 100644 index 2859cca..0000000 --- a/qml/form/SettingForm.qml +++ /dev/null @@ -1,5 +0,0 @@ -import QtQuick 2.9 - -Item { - -} diff --git a/qml/form/SettingGeneralForm.qml b/qml/form/SettingGeneralForm.qml index eb027c7..1e56adb 100644 --- a/qml/form/SettingGeneralForm.qml +++ b/qml/form/SettingGeneralForm.qml @@ -3,12 +3,18 @@ import QtQuick.Controls 2.2 Page { property alias lazyLoad: lazyLoadSwitch.checked + property alias asyncMessageDelegate: asyncMessageDelegateSwitch.checked Column { Switch { id: lazyLoadSwitch - text: "Lazy Load at Initial Sync" + text: "Lazy load at initial sync" } + Switch { + id: asyncMessageDelegateSwitch + text: "Force loading message delegates asynchronously" + } + Button { text: "Invoke GC" highlighted: true diff --git a/qml/main.qml b/qml/main.qml index 34bcb56..71938e3 100644 --- a/qml/main.qml +++ b/qml/main.qml @@ -33,6 +33,7 @@ ApplicationWindow { property alias token: matriqueController.token property alias lazyLoad: settingPage.lazyLoad + property alias asyncMessageDelegate: settingPage.asyncMessageDelegate property alias darkTheme: settingPage.darkTheme property alias miniMode: settingPage.miniMode diff --git a/res.qrc b/res.qrc index 7112288..5cafb40 100644 --- a/res.qrc +++ b/res.qrc @@ -23,7 +23,6 @@ qml/component/AvatarContainer.qml qml/form/RoomListForm.qml qml/component/AudioBubble.qml - qml/form/SettingForm.qml qml/Setting.qml qml/form/SettingAccountForm.qml qml/form/SettingAppearanceForm.qml @@ -32,6 +31,5 @@ qml/form/SettingGeneralForm.qml qml/component/EmojiPicker.qml qml/component/EmojiButton.qml - qml/component/DownloadDialog.qml diff --git a/src/controller.cpp b/src/controller.cpp index 7e0b472..5b6e9a6 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -10,8 +10,8 @@ #include #include +#include #include -#include Controller::Controller(QObject* parent) : QObject(parent) { connect(m_connection, &Connection::connected, this, &Controller::connected); @@ -74,6 +74,20 @@ void Controller::reconnect() { m_connection->connectWithToken(userID, token, ""); } +void Controller::uploadFile(Room* room) { + if (!room) return; + auto localFile = QFileDialog::getOpenFileUrl(Q_NULLPTR, tr("Save File as")); + if (!localFile.isEmpty()) { + room->uploadFile(localFile.toString(), localFile, getMIME(localFile)); + QMetaObject::Connection* const connection = new QMetaObject::Connection; + *connection = connect(room, &Room::fileTransferCompleted, + [=](QString id, QUrl localFile, QUrl mxcUrl) { + disconnect(*connection); + postFile(room, localFile, mxcUrl); + }); + } +} + void Controller::postFile(Room* room, const QUrl& localFile, const QUrl& mxcUrl) { const QString mime = getMIME(localFile); @@ -90,9 +104,7 @@ void Controller::postFile(Room* room, const QUrl& localFile, } QString Controller::getMIME(const QUrl& fileUrl) const { - QMimeDatabase* db = new QMimeDatabase(); - const QString mime = db->mimeTypeForFile(fileUrl.toLocalFile()).name(); - delete db; + const QString mime = m_db.mimeTypeForFile(fileUrl.toLocalFile()).name(); return mime; } @@ -125,3 +137,11 @@ void Controller::createDirectChat(const QString& userID) { void Controller::copyToClipboard(const QString& text) { m_clipboard->setText(text); } + +void Controller::saveFileAs(Room* room, QString eventId) { + if (!room) return; + auto fileName = QFileDialog::getSaveFileName( + Q_NULLPTR, tr("Save File as"), room->fileNameToDownload(eventId)); + if (!fileName.isEmpty()) + room->downloadFile(eventId, QUrl::fromLocalFile(fileName)); +} diff --git a/src/controller.h b/src/controller.h index 1d78006..3ddd5d3 100644 --- a/src/controller.h +++ b/src/controller.h @@ -7,6 +7,7 @@ #include #include +#include using namespace QMatrixClient; @@ -84,11 +85,15 @@ class Controller : public QObject { private: QClipboard* m_clipboard = QApplication::clipboard(); + QMimeDatabase m_db; void connected(); void resync(); void reconnect(); + QString getMIME(const QUrl& fileUrl) const; + void postFile(Room* room, const QUrl& localFile, const QUrl& mxcUrl); + signals: void connectionChanged(); void isLoginChanged(); @@ -99,13 +104,13 @@ class Controller : public QObject { void errorOccured(); public slots: - void postFile(Room* room, const QUrl& localFile, const QUrl& mxcUrl); - QString getMIME(const QUrl& fileUrl) const; + void uploadFile(Room* room); void forgetRoom(const QString& roomID); void joinRoom(const QString& alias); void createRoom(const QString& name, const QString& topic); void createDirectChat(const QString& userID); void copyToClipboard(const QString& text); + void saveFileAs(Room* room, QString eventId); }; #endif // CONTROLLER_H