浏览代码

Improve 'Handle local file editing' feature. Add loading popup. Add force sync before opening a file.'

Signed-off-by: alex-z <blackslayer4@gmail.com>
alex-z 3 年之前
父节点
当前提交
7672cb7903

+ 1 - 0
resources.qrc

@@ -36,6 +36,7 @@
         <file>src/gui/tray/ActivityItemContent.qml</file>
         <file>src/gui/tray/TalkReplyTextField.qml</file>
         <file>src/gui/tray/CallNotificationDialog.qml</file>
+        <file>src/gui/tray/EditFileLocallyLoadingDialog.qml</file>
         <file>src/gui/tray/NCBusyIndicator.qml</file>
         <file>src/gui/tray/NCToolTip.qml</file>
     </qresource>

+ 32 - 5
src/gui/folderman.cpp

@@ -1473,11 +1473,38 @@ void FolderMan::editFileLocally(const QString &accountDisplayName, const QString
         return;
     }
 
-    // In case the VFS mode is enabled and a file is not yet hydrated, we must call QDesktopServices::openUrl from a separate thread, or, there will be a freeze.
-    // To avoid searching for a specific folder and checking if the VFS is enabled - we just always call it from a separate thread.
-    QtConcurrent::run([foundFiles] {
-        QDesktopServices::openUrl(QUrl::fromLocalFile(foundFiles.first()));
-    });
+    const auto localFilePath = foundFiles.first();
+    const auto folderForFile = folderForPath(localFilePath);
+
+    if (!folderForFile) {
+        showError(accountFound, tr("Could not find a folder to sync."), relPath);
+        return;
+    }
+    
+    const auto relPathSplit = relPath.split(QLatin1Char('/'));
+    if (relPathSplit.size() > 0) {
+        Systray::instance()->createEditFileLocallyLoadingDialog(relPathSplit.last());
+    } else {
+        showError(accountFound, tr("Could not find a file for local editing. Make sure its path is valid and it is synced locally."), relPath);
+        return;
+    }
+    folderForFile->startSync();
+    _localFileEditingSyncFinishedConnections.insert(localFilePath, QObject::connect(folderForFile, &Folder::syncFinished, this,
+        [this, localFilePath](const OCC::SyncResult &result) {
+        Q_UNUSED(result);
+        const auto foundConnectionIt = _localFileEditingSyncFinishedConnections.find(localFilePath);
+        if (foundConnectionIt != std::end(_localFileEditingSyncFinishedConnections) && foundConnectionIt.value()) {
+            QObject::disconnect(foundConnectionIt.value());
+            _localFileEditingSyncFinishedConnections.erase(foundConnectionIt);
+        }
+        // In case the VFS mode is enabled and a file is not yet hydrated, we must call QDesktopServices::openUrl
+        // from a separate thread, or, there will be a freeze. To avoid searching for a specific folder and checking
+        // if the VFS is enabled - we just always call it from a separate thread.
+        QtConcurrent::run([localFilePath]() {
+            QDesktopServices::openUrl(QUrl::fromLocalFile(localFilePath));
+            Systray::instance()->destroyEditFileLocallyLoadingDialog();
+        });
+    }));
 }
 
 void FolderMan::trayOverallStatus(const QList<Folder *> &folders,

+ 2 - 0
src/gui/folderman.h

@@ -375,6 +375,8 @@ private:
 
     bool _appRestartRequired = false;
 
+    QMap<QString, QMetaObject::Connection> _localFileEditingSyncFinishedConnections;
+
     static FolderMan *_instance;
     explicit FolderMan(QObject *parent = nullptr);
     friend class OCC::Application;

+ 5 - 1
src/gui/iconutils.cpp

@@ -90,7 +90,11 @@ QImage createSvgImageWithCustomColor(const QString &fileName, const QColor &cust
         }();
 
         if (iconBaseColors.contains(customColorName)) {
-            result = QImage{QString{OCC::Theme::themePrefix} + customColorName + QStringLiteral("/") + fileName};
+            if (requestedSize.width() > 0 && requestedSize.height() > 0) {
+                result = QIcon(QString{OCC::Theme::themePrefix} + customColorName + QStringLiteral("/") + fileName).pixmap(requestedSize).toImage();
+            } else {
+                result = QImage{QString{OCC::Theme::themePrefix} + customColorName + QStringLiteral("/") + fileName};
+            }
             if (!result.isNull()) {
                 return result;
             }

+ 28 - 0
src/gui/systray.cpp

@@ -257,6 +257,34 @@ void Systray::createCallDialog(const Activity &callNotification, const AccountSt
     }
 }
 
+void Systray::createEditFileLocallyLoadingDialog(const QString &fileName)
+{
+    if (_editFileLocallyLoadingDialog) {
+        return;
+    }
+
+    qCDebug(lcSystray) << "Opening a file local editing dialog...";
+
+    const auto editFileLocallyLoadingDialog = new QQmlComponent(_trayEngine, QStringLiteral("qrc:/qml/src/gui/tray/EditFileLocallyLoadingDialog.qml"));
+
+    if (editFileLocallyLoadingDialog->isError()) {
+        qCWarning(lcSystray) << editFileLocallyLoadingDialog->errorString();
+        return;
+    }
+
+    _editFileLocallyLoadingDialog = editFileLocallyLoadingDialog->createWithInitialProperties(QVariantMap{{QStringLiteral("fileName"), fileName}});
+}
+
+void Systray::destroyEditFileLocallyLoadingDialog()
+{
+    if (!_editFileLocallyLoadingDialog) {
+        return;
+    }
+    qCDebug(lcSystray) << "Closing a file local editing dialog...";
+    _editFileLocallyLoadingDialog->deleteLater();
+    _editFileLocallyLoadingDialog = nullptr;
+}
+
 void Systray::slotCurrentUserChanged()
 {
     if (_trayEngine) {

+ 4 - 0
src/gui/systray.h

@@ -88,6 +88,8 @@ public:
     void showUpdateMessage(const QString &title, const QString &message, const QUrl &webUrl);
     void setToolTip(const QString &tip);
     void createCallDialog(const Activity &callNotification, const AccountStatePtr accountState);
+    void createEditFileLocallyLoadingDialog(const QString &fileName);
+    void destroyEditFileLocallyLoadingDialog();
 
     Q_REQUIRED_RESULT QString windowTitle() const;
     Q_REQUIRED_RESULT bool useNormalWindow() const;
@@ -160,6 +162,8 @@ private:
     AccessManagerFactory _accessManagerFactory;
 
     QSet<qlonglong> _callsAlreadyNotified;
+
+    QPointer<QObject> _editFileLocallyLoadingDialog;
 };
 
 } // namespace OCC

+ 81 - 0
src/gui/tray/EditFileLocallyLoadingDialog.qml

@@ -0,0 +1,81 @@
+import QtQuick 2.15
+import QtQuick.Window 2.15
+import Style 1.0
+import com.nextcloud.desktopclient 1.0
+import QtQuick.Layouts 1.15
+import QtQuick.Controls 2.15
+
+Window {
+    id: root
+    flags: Qt.Dialog | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint
+
+    color: "transparent"
+
+    width: 320
+    height: contentLayout.implicitHeight
+
+    property string fileName: ""
+
+    readonly property real fontPixelSize: Style.topLinePixelSize * 1.5
+    readonly property real iconWidth: fontPixelSize * 2
+
+    Component.onCompleted: {
+        Systray.forceWindowInit(root);
+        x = Screen.width / 2 - width / 2
+        y = Screen.height / 2 - height / 2
+        root.show();
+        root.raise();
+        root.requestActivate();
+    }
+
+    Rectangle {
+        id: windowBackground
+        color: Style.backgroundColor
+        radius: Style.trayWindowRadius
+        border.color: Style.ncTextColor
+        anchors.fill: parent
+    }
+
+    ColumnLayout {
+        id: contentLayout
+        anchors.left: parent.left
+        anchors.right: parent.right
+        anchors.leftMargin: Style.standardSpacing
+        anchors.rightMargin: Style.standardSpacing
+        spacing: Style.standardSpacing
+        NCBusyIndicator {
+            id: busyIndicator
+            Layout.topMargin: Style.standardSpacing
+            Layout.alignment: Qt.AlignHCenter
+            Layout.preferredWidth: root.iconWidth
+            Layout.preferredHeight: root.iconWidth
+            imageSourceSizeHeight: root.iconWidth
+            imageSourceSizeWidth: root.iconWidth
+            padding: 0
+            color: Style.ncTextColor
+            running: true
+        }
+        Label {
+            id: labelFileName
+            Layout.alignment: Qt.AlignHCenter
+            Layout.fillWidth: true
+            text: root.fileName
+            elide: Text.ElideRight
+            font.bold: true
+            font.pixelSize: root.fontPixelSize
+            color: Style.ncTextColor
+            horizontalAlignment: Text.AlignHCenter
+        }
+        Label {
+            id: labelMessage
+            Layout.alignment: Qt.AlignHCenter
+            Layout.fillWidth: true
+            Layout.bottomMargin: Style.standardSpacing
+            text: qsTr("Opening for local editing")
+            elide: Text.ElideRight
+            font.pixelSize: root.fontPixelSize
+            color: Style.ncTextColor
+            horizontalAlignment: Text.AlignHCenter
+        }
+    }
+}

+ 5 - 2
src/gui/tray/NCBusyIndicator.qml

@@ -22,6 +22,9 @@ BusyIndicator {
     property color color: Style.ncSecondaryTextColor
     property string imageSource: "image://svgimage-custom-color/change.svg/"
 
+    property int imageSourceSizeWidth: 64
+    property int imageSourceSizeHeight: 64
+
     contentItem: Image {
         id: contentImage
 
@@ -31,8 +34,8 @@ BusyIndicator {
         verticalAlignment: Image.AlignVCenter
 
         source: colourableImage ? root.imageSource + root.color : root.imageSource
-        sourceSize.width: 64
-        sourceSize.height: 64
+        sourceSize.width: root.imageSourceSizeWidth
+        sourceSize.height: root.imageSourceSizeHeight
         fillMode: Image.PreserveAspectFit
 
         mipmap: true