From: Claudio Cambra Date: Tue, 29 Nov 2022 18:07:00 +0000 (+0100) Subject: Notify user when file is locked when local editing begins X-Git-Tag: archive/raspbian/3.16.7-1_deb13u1+rpi1~1^2~12^2~11^2~88^2~7 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=10746d84412d16633a8cb50c73e61ccd7924e2ed;p=nextcloud-desktop.git Notify user when file is locked when local editing begins Signed-off-by: Claudio Cambra --- diff --git a/src/gui/editlocallyjob.cpp b/src/gui/editlocallyjob.cpp index 67c8cbdc0..489b027ed 100644 --- a/src/gui/editlocallyjob.cpp +++ b/src/gui/editlocallyjob.cpp @@ -136,6 +136,7 @@ void EditLocallyJob::proceedWithSetup() } _fileName = relPathSplit.last(); + _folderRelativePath = _localFilePath.mid(_folderForFile->cleanPath().length() + 1); _folderForFile = findFolderForFile(_relPath, _userId); @@ -542,17 +543,91 @@ void EditLocallyJob::openFile() return; } - const auto localFilePath = _localFilePath; + const auto localFilePathUrl = QUrl::fromLocalFile(_localFilePath); // 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, this]() { - _accountState->account()->setLockFileState(_relPath, _folderForFile->journalDb(), SyncFileItem::LockStatus::LockedItem); - QDesktopServices::openUrl(QUrl::fromLocalFile(localFilePath)); + QtConcurrent::run([localFilePathUrl, this]() { + if(QDesktopServices::openUrl(localFilePathUrl)) { + lockFile(); + } Systray::instance()->destroyEditFileLocallyLoadingDialog(); }); +} + +void EditLocallyJob::lockFile() +{ + Q_ASSERT(_accountState); + Q_ASSERT(_accountState->account()); + Q_ASSERT(_folderForFile); + + if (_accountState->account()->fileLockStatus(_folderForFile->journalDb(), _folderRelativePath) == SyncFileItem::LockStatus::LockedItem) { + fileLockSuccess(true); + return; + } + + _folderConnections.append(connect(_accountState->account().data(), &Account::lockFileSuccess, + this, [this] { + _folderForFile->journalDb()->schedulePathForRemoteDiscovery(_relPath); + _folderForFile->scheduleThisFolderSoon(); + })); + _folderConnections.append(connect(_folderForFile, &Folder::syncFinished, + this, [this](const OCC::SyncResult &result) { + Q_UNUSED(result) + fileLockSuccess(); + })); + _folderConnections.append(connect(_accountState->account().data(), &Account::lockFileError, + this, &EditLocallyJob::fileLockError)); + + _folderForFile->accountState()->account()->setLockFileState(_relPath, + _folderForFile->journalDb(), + SyncFileItem::LockStatus::LockedItem); +} + +void EditLocallyJob::disconnectFolderSignals() +{ + for (const auto &connection : qAsConst(_folderConnections)) { + disconnect(connection); + } +} + +void EditLocallyJob::fileLockSuccess(const bool existingLock) +{ + qCDebug(lcEditLocallyJob()) << "File lock succeeded, showing notification" << _relPath; + + SyncJournalFileRecord rec; + Q_ASSERT(_folderForFile->journalDb()->getFileRecord(_folderRelativePath, &rec)); + Q_ASSERT(rec.isValid()); + Q_ASSERT(rec._lockstate._locked); + + const auto lockExpirationTime = rec._lockstate._lockTime + rec._lockstate._lockTimeout; + const auto remainingTime = QDateTime::currentDateTime().secsTo(QDateTime::fromSecsSinceEpoch(lockExpirationTime)); + + static constexpr auto SECONDS_PER_MINUTE = 60; + const auto remainingTimeInMinutes = static_cast(remainingTime > 0 ? remainingTime / SECONDS_PER_MINUTE : 0); + + const auto notificationTitle = existingLock ? tr("File %1 already locked.") : + tr("File %1 now locked."); + + Systray::instance()->showMessage(notificationTitle.arg(_fileName), + tr("Lock will last for %1 minutes. " + "You can also unlock this file manually once you are finished editing.").arg(remainingTimeInMinutes), + QSystemTrayIcon::Information); + + disconnectFolderSignals(); + Q_EMIT finished(); +} + +void EditLocallyJob::fileLockError(const QString &errorMessage) +{ + qCWarning(lcEditLocallyJob()) << "File lock failed, showing notification" << _relPath << errorMessage; + + Systray::instance()->showMessage(tr("File %1 could not be locked."), + errorMessage, + QSystemTrayIcon::Warning); - Q_EMIT fileOpened(); + disconnectFolderSignals(); + Q_EMIT finished(); } } diff --git a/src/gui/editlocallyjob.h b/src/gui/editlocallyjob.h index a2293bffc..9099804ad 100644 --- a/src/gui/editlocallyjob.h +++ b/src/gui/editlocallyjob.h @@ -45,7 +45,7 @@ public: signals: void setupFinished(); void error(const QString &message, const QString &informativeText); - void fileOpened(); + void finished(); public slots: void startSetup(); @@ -72,6 +72,11 @@ private slots: void slotDirectoryListingIterated(const QString &name, const QMap &properties); void openFile(); + void lockFile(); + + void fileLockSuccess(const bool existingLock = false); + void fileLockError(const QString &errorMessage); + void disconnectFolderSignals(); private: [[nodiscard]] bool checkIfFileParentSyncIsNeeded(); // returns true if sync will be needed, false otherwise @@ -90,9 +95,11 @@ private: QString _fileName; QString _localFilePath; + QString _folderRelativePath; Folder *_folderForFile = nullptr; std::unique_ptr _checkTokenJob; QMetaObject::Connection _syncTerminatedConnection = {}; + QVector _folderConnections; }; } diff --git a/src/gui/editlocallymanager.cpp b/src/gui/editlocallymanager.cpp index 09776b31a..c301d4b42 100644 --- a/src/gui/editlocallymanager.cpp +++ b/src/gui/editlocallymanager.cpp @@ -83,7 +83,7 @@ void EditLocallyManager::createJob(const QString &userId, connect(job.data(), &EditLocallyJob::error, this, removeJob); - connect(job.data(), &EditLocallyJob::fileOpened, + connect(job.data(), &EditLocallyJob::finished, this, removeJob); connect(job.data(), &EditLocallyJob::setupFinished, job.data(), setupJob);