Browse Source

Validate batch snapshots and freeze deletion confirmation context

master
evgeny 3 days ago
parent
commit
1ed467d236
  1. 5
      tools/chatgui/src/member_files/batch.cpp
  2. 2
      tools/chatgui/src/member_files/batch.h
  3. 18
      tools/chatgui/src/member_files/browser.cpp

5
tools/chatgui/src/member_files/batch.cpp

@ -133,7 +133,8 @@ void MemberFileBatch::next() {
if (m_queue.isEmpty() && !m_verify.isEmpty()) { m_queue = m_verify; m_verify.clear(); } if (m_queue.isEmpty() && !m_verify.isEmpty()) { m_queue = m_verify; m_verify.clear(); }
if (m_queue.isEmpty()) { finish(); return; } if (m_queue.isEmpty()) { finish(); return; }
const auto entry = m_queue.first(); const auto entry = m_queue.first();
if (!pathBytes(entry.remote, true) || (m_mode != Remove && !pathBytes(entry.local, false))) { if (!pathBytes(entry.remote, true) || (m_mode != Remove && !pathBytes(entry.local, false)) ||
(m_mode == Download && (entry.version.size() != 16 || mf_zero((const uint8_t*)entry.version.constData(), 16)))) {
finish(text("Cannot copy this path: %1").arg(entry.remote)); return; finish(text("Cannot copy this path: %1").arg(entry.remote)); return;
} }
progress(text("Processed %1, skipped %2, remaining %3: %4").arg(m_done).arg(m_skipped).arg(m_queue.size()).arg(entry.remote), -1); progress(text("Processed %1, skipped %2, remaining %3: %4").arg(m_done).arg(m_skipped).arg(m_queue.size()).arg(entry.remote), -1);
@ -267,7 +268,7 @@ void MemberFileBatch::finish(const QString& error) {
if (m_finished) return; if (m_finished) return;
m_finished = true; m_finished = true;
bool ok = error.isEmpty() && !m_cancelled; bool ok = error.isEmpty() && !m_cancelled;
QString summary = text("Completed: %1, skipped: %2").arg(m_done).arg(m_skipped); QString summary = text("Completed: %1, skipped: %2, remaining: %3").arg(m_done).arg(m_skipped).arg(m_queue.size());
if (!ok) summary = (m_cancelled ? text("Copy cancelled") : error) + " — " + summary; if (!ok) summary = (m_cancelled ? text("Copy cancelled") : error) + " — " + summary;
if (ok) DEBUG_INFO(DEBUG_CATEGORY_MEDIA, "file batch: %s", qPrintable(summary)); if (ok) DEBUG_INFO(DEBUG_CATEGORY_MEDIA, "file batch: %s", qPrintable(summary));
else DEBUG_WARN(DEBUG_CATEGORY_MEDIA, "file batch: %s", qPrintable(summary)); else DEBUG_WARN(DEBUG_CATEGORY_MEDIA, "file batch: %s", qPrintable(summary));

2
tools/chatgui/src/member_files/batch.h

@ -47,7 +47,7 @@ private:
QList<MemberFileEntry> m_queue, m_verify; QList<MemberFileEntry> m_queue, m_verify;
QSet<QString> m_seen; QSet<QString> m_seen;
QStringList m_roots; QStringList m_roots;
QString m_temporary, m_error; QString m_temporary;
QThreadPool m_pool; QThreadPool m_pool;
std::atomic_bool m_cancelled{false}; std::atomic_bool m_cancelled{false};
bool m_work = false, m_finished = false; bool m_work = false, m_finished = false;

18
tools/chatgui/src/member_files/browser.cpp

@ -547,7 +547,7 @@ void MemberFileBrowser::publishExport(const QStringList& paths, bool clipboard)
DEBUG_INFO(DEBUG_CATEGORY_MEDIA, "file browser: exporting entries=%d clipboard=%d", int(paths.size()), clipboard); DEBUG_INFO(DEBUG_CATEGORY_MEDIA, "file browser: exporting entries=%d clipboard=%d", int(paths.size()), clipboard);
if (clipboard) { if (clipboard) {
QGuiApplication::clipboard()->setMimeData(mime); QGuiApplication::clipboard()->setMimeData(mime);
m_status->setText(text("File copied. Paste it in your file manager.")); m_status->setText(text("Selection copied. Paste it in your file manager."));
} else { } else {
auto* drag = new QDrag(m_entries); drag->setMimeData(mime); drag->exec(Qt::CopyAction, Qt::CopyAction); auto* drag = new QDrag(m_entries); drag->setMimeData(mime); drag->exec(Qt::CopyAction, Qt::CopyAction);
} }
@ -556,14 +556,19 @@ void MemberFileBrowser::publishExport(const QStringList& paths, bool clipboard)
void MemberFileBrowser::exportFile(bool clipboard, const QString& destination) { void MemberFileBrowser::exportFile(bool clipboard, const QString& destination) {
if (!m_copyAction->isEnabled()) { if (!m_copyAction->isEnabled()) {
DEBUG_WARN(DEBUG_CATEGORY_MEDIA, "file browser: export unavailable"); DEBUG_WARN(DEBUG_CATEGORY_MEDIA, "file browser: export unavailable");
m_status->setText(text("Select a file and finish the current transfer first")); return; m_status->setText(text("Select entries and finish the current transfer first")); return;
} }
auto entries = selectedEntries(); if (entries.isEmpty()) return; auto entries = selectedEntries(); if (entries.isEmpty()) return;
QString base = destination.isEmpty() ? QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/file-exports" : destination; QString base = destination.isEmpty() ? QStandardPaths::writableLocation(QStandardPaths::CacheLocation) : destination;
if (base.isEmpty()) {
DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "file browser: export has no cache location");
m_status->setText(text("Cannot prepare a local copy")); return;
}
if (destination.isEmpty()) base += "/file-exports";
m_exportId = requestId(); m_exportResult.clear(); m_openAfter = false; m_exportId = requestId(); m_exportResult.clear(); m_openAfter = false;
quint64 id = m_exportId; quint64 id = m_exportId;
auto* batch = createBatch(MemberFileBatch::Download); auto* batch = createBatch(MemberFileBatch::Download);
batch->finished = [this, batch, clipboard, destination](bool ok, const QString& summary, const QStringList& roots) { batch->finished = [this, batch, clipboard](bool ok, const QString& summary, const QStringList& roots) {
m_batch = nullptr; m_exportId = 0; m_progress->hide(); m_uploadStatus->setText(summary); m_batch = nullptr; m_exportId = 0; m_progress->hide(); m_uploadStatus->setText(summary);
m_exportResult = ok ? roots : QStringList(); batch->deleteLater(); updateActions(); m_exportResult = ok ? roots : QStringList(); batch->deleteLater(); updateActions();
if (ok && clipboard) publishExport(roots, true); if (ok && clipboard) publishExport(roots, true);
@ -637,10 +642,13 @@ void MemberFileBrowser::mutate(uint8_t command) {
if (command == MF_REMOVE_PATH) { if (command == MF_REMOVE_PATH) {
auto entries = selectedEntries(); if (entries.isEmpty()) return; auto entries = selectedEntries(); if (entries.isEmpty()) return;
QPointer<MemberFileBrowser> guard(this); QPointer<MemberFileBrowser> guard(this);
m_dropId = requestId(); updateActions();
QString prompt = entries.size() == 1 ? text("Delete %1?").arg(entries.first().remote) : QString prompt = entries.size() == 1 ? text("Delete %1?").arg(entries.first().remote) :
text("Delete %1 selected entries? Non-empty folders will not be removed.").arg(entries.size()); text("Delete %1 selected entries? Non-empty folders will not be removed.").arg(entries.size());
auto answer = QMessageBox::question(this, text("Delete"), prompt, QMessageBox::Yes | QMessageBox::No, QMessageBox::No); auto answer = QMessageBox::question(this, text("Delete"), prompt, QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
if (!guard || answer != QMessageBox::Yes) return; if (!guard) return;
bool cancelled = !m_dropId; m_dropId = 0; updateActions();
if (cancelled || answer != QMessageBox::Yes) return;
auto* batch = createBatch(MemberFileBatch::Remove); auto* batch = createBatch(MemberFileBatch::Remove);
batch->finished = [this, batch](bool, const QString& summary, const QStringList&) { batch->finished = [this, batch](bool, const QString& summary, const QStringList&) {
m_batch = nullptr; m_progress->hide(); m_uploadStatus->setText(summary); batch->deleteLater(); updateActions(); refresh(); m_batch = nullptr; m_progress->hide(); m_uploadStatus->setText(summary); batch->deleteLater(); updateActions(); refresh();

Loading…
Cancel
Save