Prevent new packs from overwriting the default pack by accident

This commit is contained in:
Nicolas Werner 2023-05-19 23:06:14 +02:00
parent c1fa5b18f2
commit 72a9ee907d
No known key found for this signature in database
GPG key ID: C8D75E610773F2D9
3 changed files with 47 additions and 1 deletions

View file

@ -82,8 +82,10 @@ SingleImagePackModel *
ImagePackListModel::newPack(bool inRoom) ImagePackListModel::newPack(bool inRoom)
{ {
ImagePackInfo info{}; ImagePackInfo info{};
if (inRoom) if (inRoom) {
info.source_room = room_id; info.source_room = room_id;
info.state_key = SingleImagePackModel::unconflictingStatekey(room_id, "");
}
return new SingleImagePackModel(info); return new SingleImagePackModel(info);
} }

View file

@ -8,6 +8,8 @@
#include <QFileInfo> #include <QFileInfo>
#include <QMimeDatabase> #include <QMimeDatabase>
#include <unordered_set>
#include <mtx/responses/media.hpp> #include <mtx/responses/media.hpp>
#include "Cache_p.h" #include "Cache_p.h"
@ -237,6 +239,12 @@ SingleImagePackModel::setStatekey(QString val)
auto val_ = val.toStdString(); auto val_ = val.toStdString();
if (val_ != statekey_) { if (val_ != statekey_) {
statekey_ = val_; statekey_ = val_;
// prevent deleting current pack
if (!roomid_.empty() && statekey_ != old_statekey_) {
statekey_ = unconflictingStatekey(roomid_, statekey_);
}
emit statekeyChanged(); emit statekeyChanged();
} }
} }
@ -290,6 +298,7 @@ SingleImagePackModel::save()
tr("Failed to delete old image pack: %1") tr("Failed to delete old image pack: %1")
.arg(QString::fromStdString(e->matrix_error.error))); .arg(QString::fromStdString(e->matrix_error.error)));
}); });
old_statekey_ = statekey_;
} }
http::client()->send_state_event( http::client()->send_state_event(
@ -398,6 +407,7 @@ std::string
SingleImagePackModel::unconflictingShortcode(const std::string &shortcode) SingleImagePackModel::unconflictingShortcode(const std::string &shortcode)
{ {
if (pack.images.count(shortcode)) { if (pack.images.count(shortcode)) {
// more images won't fit in an event anyway
for (int i = 0; i < 64'000; i++) { for (int i = 0; i < 64'000; i++) {
auto tempCode = shortcode + std::to_string(i); auto tempCode = shortcode + std::to_string(i);
if (!pack.images.count(tempCode)) { if (!pack.images.count(tempCode)) {
@ -408,6 +418,38 @@ SingleImagePackModel::unconflictingShortcode(const std::string &shortcode)
return shortcode; return shortcode;
} }
std::string
SingleImagePackModel::unconflictingStatekey(const std::string &roomid, const std::string &key)
{
if (roomid.empty())
return key;
std::unordered_set<std::string> statekeys;
auto currentPacks =
cache::client()->getStateEventsWithType<mtx::events::msc2545::ImagePack>(roomid);
for (const auto &pack : currentPacks) {
if (!pack.content.images.empty())
statekeys.insert(pack.state_key);
}
auto defaultPack = cache::client()->getStateEvent<mtx::events::msc2545::ImagePack>(roomid);
if (defaultPack && defaultPack->content.images.size()) {
statekeys.insert(defaultPack->state_key);
}
if (statekeys.count(key)) {
// arbitrary count. More than 64k image packs in a room are unlikely and if you have that,
// you probably know what you are doing :)
for (int i = 0; i < 64'000; i++) {
auto tempCode = key + std::to_string(i);
if (!statekeys.count(tempCode)) {
return tempCode;
}
}
}
return key;
}
void void
SingleImagePackModel::addImageCb(std::string uri, std::string filename, mtx::common::ImageInfo info) SingleImagePackModel::addImageCb(std::string uri, std::string filename, mtx::common::ImageInfo info)
{ {

View file

@ -71,6 +71,8 @@ public:
Q_INVOKABLE void remove(int index); Q_INVOKABLE void remove(int index);
Q_INVOKABLE void setAvatar(QUrl file); Q_INVOKABLE void setAvatar(QUrl file);
static std::string unconflictingStatekey(const std::string &roomid, const std::string &key);
signals: signals:
void globallyEnabledChanged(); void globallyEnabledChanged();
void statekeyChanged(); void statekeyChanged();