Skip to content

Commit

Permalink
Notify user when file is locked when local editing begins
Browse files Browse the repository at this point in the history
Signed-off-by: Claudio Cambra <[email protected]>
  • Loading branch information
claucambra authored and allexzander committed Dec 5, 2022
1 parent 5ffef3f commit 5b51f8c
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 7 deletions.
85 changes: 80 additions & 5 deletions src/gui/editlocallyjob.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ void EditLocallyJob::proceedWithSetup()
}

_fileName = relPathSplit.last();
_folderRelativePath = _localFilePath.mid(_folderForFile->cleanPath().length() + 1);

Systray::instance()->destroyEditFileLocallyLoadingDialog();
Q_EMIT setupFinished();
Expand Down Expand Up @@ -307,17 +308,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<int>(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();
}

}
9 changes: 8 additions & 1 deletion src/gui/editlocallyjob.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class EditLocallyJob : public QObject
signals:
void setupFinished();
void error(const QString &message, const QString &informativeText);
void fileOpened();
void finished();

public slots:
void startSetup();
Expand All @@ -63,6 +63,11 @@ private slots:

void disconnectSyncFinished() const;
void openFile();
void lockFile();

void fileLockSuccess(const bool existingLock = false);
void fileLockError(const QString &errorMessage);
void disconnectFolderSignals();

private:
bool _tokenVerified = false;
Expand All @@ -74,8 +79,10 @@ private slots:

QString _fileName;
QString _localFilePath;
QString _folderRelativePath;
Folder *_folderForFile = nullptr;
std::unique_ptr<SimpleApiJob> _checkTokenJob;
QVector<QMetaObject::Connection> _folderConnections;
};

}
2 changes: 1 addition & 1 deletion src/gui/editlocallymanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,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);
Expand Down

0 comments on commit 5b51f8c

Please sign in to comment.