Rewrite FileDialog in C++ && add setting to force async load timelime.

Also fixes repeat section label and empty space when message is redacted.

Fixes #27
This commit is contained in:
Black Hat 2018-08-14 14:05:41 +08:00
parent 1e5fda47ab
commit 09fdd52524
11 changed files with 63 additions and 55 deletions

View File

@ -8,6 +8,8 @@ import "form"
Page { Page {
property alias lazyLoad: generalForm.lazyLoad property alias lazyLoad: generalForm.lazyLoad
property alias asyncMessageDelegate: generalForm.asyncMessageDelegate
property alias darkTheme: appearanceForm.darkTheme property alias darkTheme: appearanceForm.darkTheme
property alias miniMode: appearanceForm.miniMode property alias miniMode: appearanceForm.miniMode

View File

@ -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()
}

View File

@ -17,7 +17,7 @@ Item {
onDownloadedChanged: downloaded && openOnFinished ? openSavedFile() : {} onDownloadedChanged: downloaded && openOnFinished ? openSavedFile() : {}
function saveFileAs() { function saveFileAs() {
Qt.createComponent("DownloadDialog.qml").createObject(this).open() matriqueController.saveFileAs(currentRoom, eventId)
} }
function downloadAndOpen() function downloadAndOpen()

View File

@ -4,7 +4,7 @@ import QtQuick.Controls.Material 2.2
import Matrique 0.1 import Matrique 0.1
Item { Item {
id: messageDelegate readonly property bool hidden: marks === EventStatus.Redacted || marks === EventStatus.Hidden
readonly property bool darkTheme: Material.theme == Material.Dark readonly property bool darkTheme: Material.theme == Material.Dark
readonly property color background: darkTheme ? "#242424" : "lightgrey" readonly property color background: darkTheme ? "#242424" : "lightgrey"
@ -12,7 +12,7 @@ Item {
readonly property bool sentByMe: author === currentRoom.localUser readonly property bool sentByMe: author === currentRoom.localUser
readonly property bool isState: eventType === "state" || eventType === "emote" readonly property bool isState: eventType === "state" || eventType === "emote"
visible: marks !== EventStatus.Hidden id: messageDelegate
z: -5 z: -5
width: delegateLoader.width width: delegateLoader.width
@ -29,8 +29,10 @@ Item {
Loader { Loader {
id: delegateLoader id: delegateLoader
asynchronous: setting.asyncMessageDelegate
source: { source: {
if (eventType == "redaction") return "" if (eventType == "redaction" || hidden) return ""
switch (eventType) { switch (eventType) {
case "state": case "state":
case "emote": case "emote":

View File

@ -191,12 +191,15 @@ Item {
} }
delegate: Column { delegate: Column {
readonly property bool hidden: marks === EventStatus.Redacted || marks === EventStatus.Hidden
width: parent.width width: parent.width
height: hidden ? -8 : undefined
spacing: 8 spacing: 8
RowLayout { RowLayout {
width: parent.width * 0.8 width: parent.width * 0.8
visible: section !== aboveSection visible: section !== aboveSection && !hidden
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
spacing: 8 spacing: 8
@ -300,30 +303,19 @@ Item {
contentItem: MaterialIcon { icon: "\ue226" } contentItem: MaterialIcon { icon: "\ue226" }
onClicked: fileDialog.visible = true onClicked: {
var fileTransferProgressCallback = function(id, sent, total) {
FileDialog { inputField.progress = sent / total
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)
} }
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)
} }
} }

View File

@ -1,5 +0,0 @@
import QtQuick 2.9
Item {
}

View File

@ -3,12 +3,18 @@ import QtQuick.Controls 2.2
Page { Page {
property alias lazyLoad: lazyLoadSwitch.checked property alias lazyLoad: lazyLoadSwitch.checked
property alias asyncMessageDelegate: asyncMessageDelegateSwitch.checked
Column { Column {
Switch { Switch {
id: lazyLoadSwitch id: lazyLoadSwitch
text: "Lazy Load at Initial Sync" text: "Lazy load at initial sync"
} }
Switch {
id: asyncMessageDelegateSwitch
text: "Force loading message delegates asynchronously"
}
Button { Button {
text: "Invoke GC" text: "Invoke GC"
highlighted: true highlighted: true

View File

@ -33,6 +33,7 @@ ApplicationWindow {
property alias token: matriqueController.token property alias token: matriqueController.token
property alias lazyLoad: settingPage.lazyLoad property alias lazyLoad: settingPage.lazyLoad
property alias asyncMessageDelegate: settingPage.asyncMessageDelegate
property alias darkTheme: settingPage.darkTheme property alias darkTheme: settingPage.darkTheme
property alias miniMode: settingPage.miniMode property alias miniMode: settingPage.miniMode

View File

@ -23,7 +23,6 @@
<file>qml/component/AvatarContainer.qml</file> <file>qml/component/AvatarContainer.qml</file>
<file>qml/form/RoomListForm.qml</file> <file>qml/form/RoomListForm.qml</file>
<file>qml/component/AudioBubble.qml</file> <file>qml/component/AudioBubble.qml</file>
<file>qml/form/SettingForm.qml</file>
<file>qml/Setting.qml</file> <file>qml/Setting.qml</file>
<file>qml/form/SettingAccountForm.qml</file> <file>qml/form/SettingAccountForm.qml</file>
<file>qml/form/SettingAppearanceForm.qml</file> <file>qml/form/SettingAppearanceForm.qml</file>
@ -32,6 +31,5 @@
<file>qml/form/SettingGeneralForm.qml</file> <file>qml/form/SettingGeneralForm.qml</file>
<file>qml/component/EmojiPicker.qml</file> <file>qml/component/EmojiPicker.qml</file>
<file>qml/component/EmojiButton.qml</file> <file>qml/component/EmojiButton.qml</file>
<file>qml/component/DownloadDialog.qml</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -10,8 +10,8 @@
#include <QClipboard> #include <QClipboard>
#include <QFile> #include <QFile>
#include <QFileDialog>
#include <QImage> #include <QImage>
#include <QMimeDatabase>
Controller::Controller(QObject* parent) : QObject(parent) { Controller::Controller(QObject* parent) : QObject(parent) {
connect(m_connection, &Connection::connected, this, &Controller::connected); connect(m_connection, &Connection::connected, this, &Controller::connected);
@ -74,6 +74,20 @@ void Controller::reconnect() {
m_connection->connectWithToken(userID, token, ""); 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, void Controller::postFile(Room* room, const QUrl& localFile,
const QUrl& mxcUrl) { const QUrl& mxcUrl) {
const QString mime = getMIME(localFile); const QString mime = getMIME(localFile);
@ -90,9 +104,7 @@ void Controller::postFile(Room* room, const QUrl& localFile,
} }
QString Controller::getMIME(const QUrl& fileUrl) const { QString Controller::getMIME(const QUrl& fileUrl) const {
QMimeDatabase* db = new QMimeDatabase(); const QString mime = m_db.mimeTypeForFile(fileUrl.toLocalFile()).name();
const QString mime = db->mimeTypeForFile(fileUrl.toLocalFile()).name();
delete db;
return mime; return mime;
} }
@ -125,3 +137,11 @@ void Controller::createDirectChat(const QString& userID) {
void Controller::copyToClipboard(const QString& text) { void Controller::copyToClipboard(const QString& text) {
m_clipboard->setText(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));
}

View File

@ -7,6 +7,7 @@
#include <QObject> #include <QObject>
#include <QApplication> #include <QApplication>
#include <QMimeDatabase>
using namespace QMatrixClient; using namespace QMatrixClient;
@ -84,11 +85,15 @@ class Controller : public QObject {
private: private:
QClipboard* m_clipboard = QApplication::clipboard(); QClipboard* m_clipboard = QApplication::clipboard();
QMimeDatabase m_db;
void connected(); void connected();
void resync(); void resync();
void reconnect(); void reconnect();
QString getMIME(const QUrl& fileUrl) const;
void postFile(Room* room, const QUrl& localFile, const QUrl& mxcUrl);
signals: signals:
void connectionChanged(); void connectionChanged();
void isLoginChanged(); void isLoginChanged();
@ -99,13 +104,13 @@ class Controller : public QObject {
void errorOccured(); void errorOccured();
public slots: public slots:
void postFile(Room* room, const QUrl& localFile, const QUrl& mxcUrl); void uploadFile(Room* room);
QString getMIME(const QUrl& fileUrl) const;
void forgetRoom(const QString& roomID); void forgetRoom(const QString& roomID);
void joinRoom(const QString& alias); void joinRoom(const QString& alias);
void createRoom(const QString& name, const QString& topic); void createRoom(const QString& name, const QString& topic);
void createDirectChat(const QString& userID); void createDirectChat(const QString& userID);
void copyToClipboard(const QString& text); void copyToClipboard(const QString& text);
void saveFileAs(Room* room, QString eventId);
}; };
#endif // CONTROLLER_H #endif // CONTROLLER_H