зеркало из https://github.com/nextcloud/desktop.git
Merge pull request #4990 from nextcloud/bugfix/local-editing-sync-and-loading-indicator
Improve 'Handle local file editing' feature. Add loading popup. Add force sync before opening a file.
This commit is contained in:
Коммит
35dec82616
|
@ -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>
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче