Share avatar metadata downloads and cancel closed desktop galleries
This commit is contained in:
1 parent
6bd6ea540c
commit
27fd9ee62d
2 files changed
+39
-7
No files matched your search
@@ -154,6 +154,10 @@ QImage AvatarManager::fetch(const Ref& ref, bool original, bool gallery) {
|
||||
Job job; job.ref = ref; job.original = original; job.gallery = gallery; job.generation = m_generation;
|
||||
const auto record = m_records.value(ref.hash);
|
||||
job.file = record.original.isEmpty() ? ref.hash + ".json" : (original ? record.original : record.preview);
|
||||
if (record.original.isEmpty()) {
|
||||
for (const auto& active : m_jobs) if (!active.upload && active.ref.hash == ref.hash && active.file == job.file) return {};
|
||||
for (const auto& queued : m_queue) if (!queued.upload && queued.ref.hash == ref.hash && queued.file == job.file) return {};
|
||||
}
|
||||
enqueue(job); pump(); return {};
|
||||
}
|
||||
|
||||
@@ -168,20 +172,41 @@ void AvatarManager::openGallery(const QString& channel, quint64 owner) {
|
||||
}
|
||||
|
||||
void AvatarManager::closeGallery() {
|
||||
m_galleryEpoch++;
|
||||
if (m_listId && gui_bridge_is_uasync_ready()) {
|
||||
auto* q = (mf_cancel_request*)u_calloc(1, sizeof(mf_cancel_request));
|
||||
if (q) { q->inst = gui_bridge_get_inst(); q->id = m_listId; gui_bridge_post_uasync_fn(member_files_gui_cancel, q); }
|
||||
else DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "avatar: gallery cancel allocation failed");
|
||||
}
|
||||
m_listId = 0; m_galleryRef = {}; m_gallery.clear(); m_catalog.clear(); m_listRetries = 0;
|
||||
QQueue<Job> keep; while (!m_queue.isEmpty()) { const auto job = m_queue.dequeue(); if (!job.gallery) keep.enqueue(job); }
|
||||
auto needed = [this](const Job& job) {
|
||||
const QString context = key(job.ref.group, job.ref.owner);
|
||||
return !job.original && m_wanted.contains(context) && m_refs.value(context).hash == job.ref.hash;
|
||||
};
|
||||
for (auto id : m_jobs.keys()) {
|
||||
auto& job = m_jobs[id];
|
||||
if (!job.gallery) continue;
|
||||
if (needed(job)) { job.gallery = false; continue; }
|
||||
if (gui_bridge_is_uasync_ready()) {
|
||||
auto* q = (mf_cancel_request*)u_calloc(1, sizeof(mf_cancel_request));
|
||||
if (q) { q->inst = gui_bridge_get_inst(); q->id = id; gui_bridge_post_uasync_fn(member_files_gui_cancel, q); }
|
||||
else DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "avatar: cancel allocation failed id=%llu", (unsigned long long)id);
|
||||
}
|
||||
finish(id, MF_CANCELLED);
|
||||
}
|
||||
QQueue<Job> keep; while (!m_queue.isEmpty()) {
|
||||
auto job = m_queue.dequeue(); if (job.gallery && needed(job)) job.gallery = false;
|
||||
if (!job.gallery) keep.enqueue(job);
|
||||
}
|
||||
m_queue = keep;
|
||||
}
|
||||
|
||||
void AvatarManager::listGallery(quint64 cursor, const QByteArray& version) {
|
||||
if (!gui_bridge_is_uasync_ready() || !m_galleryRef.server) return;
|
||||
auto* q = (mf_gui_request*)u_calloc(1, sizeof(mf_gui_request));
|
||||
if (!q) { DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "avatar: catalog allocation failed"); emit galleryError(text("Cannot load avatars")); return; }
|
||||
do { m_listId = QRandomGenerator::global()->generate64(); } while (!m_listId || m_jobs.contains(m_listId));
|
||||
m_listCursor = cursor;
|
||||
q->inst = gui_bridge_get_inst(); q->group = m_galleryRef.group; q->server = m_galleryRef.server;
|
||||
q->message.kind = MF_REQUEST; q->message.command = MF_LIST; q->message.request_id = m_listId;
|
||||
q->message.owner = m_galleryRef.owner; q->message.cursor = cursor; memcpy(q->message.path, "avatars", 8);
|
||||
@@ -312,7 +337,7 @@ void AvatarManager::enqueue(const Job& job) {
|
||||
for (const auto& old : m_queue) if ((old.upload == job.upload && old.ref.group == job.ref.group && old.ref.owner == job.ref.owner &&
|
||||
(job.upload || (old.ref.hash == job.ref.hash && old.original == job.original))) ||
|
||||
(!job.upload && !old.upload && old.ref.hash == job.ref.hash && old.original == job.original)) return;
|
||||
if (job.upload) m_queue.prepend(job); else m_queue.enqueue(job);
|
||||
if (job.upload || job.original) m_queue.prepend(job); else m_queue.enqueue(job);
|
||||
}
|
||||
|
||||
void AvatarManager::pump() {
|
||||
@@ -378,9 +403,9 @@ void AvatarManager::onResponse(const uint8_t* data, int length) {
|
||||
response.owner != m_galleryRef.owner || response.command != MF_LIST || strcmp(response.path, "avatars")) return;
|
||||
m_listId = 0;
|
||||
if ((response.status == MF_STALE || response.status == MF_BUSY) && m_listRetries++ < 3) {
|
||||
m_catalog.clear(); const Ref source = m_galleryRef;
|
||||
QTimer::singleShot(1000, this, [this, source] {
|
||||
if (source.group == m_galleryRef.group && source.owner == m_galleryRef.owner && source.server == m_galleryRef.server) listGallery();
|
||||
m_catalog.clear(); const quint64 epoch = m_galleryEpoch;
|
||||
QTimer::singleShot(1000, this, [this, epoch] {
|
||||
if (epoch == m_galleryEpoch) listGallery();
|
||||
}); return;
|
||||
}
|
||||
if (response.status) {
|
||||
@@ -400,7 +425,13 @@ void AvatarManager::onResponse(const uint8_t* data, int length) {
|
||||
m_catalog[QString::fromLatin1(file).left(64)] = mf_get64(p + 11);
|
||||
at += MF_ENTRY_HEADER + n;
|
||||
}
|
||||
if (response.more) { listGallery(response.cursor, QByteArray((const char*)response.version, 16)); return; }
|
||||
if (response.more) {
|
||||
if (response.cursor <= m_listCursor) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_MEDIA, "avatar: catalog cursor stalled=%llu", (unsigned long long)response.cursor);
|
||||
emit galleryError(text("Invalid directory response")); return;
|
||||
}
|
||||
listGallery(response.cursor, QByteArray((const char*)response.version, 16)); return;
|
||||
}
|
||||
m_gallery = m_catalog.keys();
|
||||
std::sort(m_gallery.begin(), m_gallery.end(), [this](const QString& a, const QString& b) {
|
||||
return m_catalog[a] != m_catalog[b] ? m_catalog[a] > m_catalog[b] : a < b;
|
||||
@@ -445,7 +476,7 @@ void AvatarManager::onTransfer(const uint8_t* data, int length) {
|
||||
if (snapshot.file.endsWith(".json")) {
|
||||
m_records[snapshot.ref.hash] = result.record;
|
||||
auto& job = m_jobs[snapshot.id]; job.file = snapshot.original ? result.record.original : result.record.preview;
|
||||
transfer(job); return;
|
||||
transfer(job); notify(snapshot.ref.hash); return;
|
||||
}
|
||||
const QString cacheKey = snapshot.ref.hash + (snapshot.original ? ":original" : "");
|
||||
m_images.insert(cacheKey, new QImage(result.image), qMax(1, int(result.image.sizeInBytes() / 1024)));
|
||||
|
||||
@@ -80,6 +80,7 @@ private:
|
||||
QStringList m_gallery;
|
||||
QMap<QString, quint64> m_catalog;
|
||||
quint64 m_listId = 0;
|
||||
quint64 m_galleryEpoch = 0, m_listCursor = 0;
|
||||
unsigned m_listRetries = 0;
|
||||
QThreadPool m_pool;
|
||||
QTimer m_timer;
|
||||
|
||||
Reference in new issue
Block a user