Page MenuHomePhorge

D341.1786141036.diff
No OneTemporary

Size
21 KB
Referenced Files
None
Subscribers
None

D341.1786141036.diff

diff --git a/src/contents/ui/room-settings/RoomStickerPackItemDelegate.qml b/src/contents/ui/room-settings/RoomStickerPackItemDelegate.qml
--- a/src/contents/ui/room-settings/RoomStickerPackItemDelegate.qml
+++ b/src/contents/ui/room-settings/RoomStickerPackItemDelegate.qml
@@ -63,8 +63,8 @@
send(content);
}
- property var sendAccountData: Kazv.AsyncHandler {
- trigger: () => matrixSession.sendAccountData(Helpers.imagePackRoomsEventType, content);
+ property var updateStickerRooms: Kazv.AsyncHandler {
+ trigger: () => matrixSession.updateStickerRooms(content);
property var content
onResolved: (success, data) => {
if (!success) {
@@ -74,7 +74,7 @@
}
function send(content) {
- sendAccountData.content = content;
- sendAccountData.call();
+ updateStickerRooms.content = content;
+ updateStickerRooms.call();
}
}
diff --git a/src/contents/ui/room-settings/RoomStickerPacksPage.qml b/src/contents/ui/room-settings/RoomStickerPacksPage.qml
--- a/src/contents/ui/room-settings/RoomStickerPacksPage.qml
+++ b/src/contents/ui/room-settings/RoomStickerPacksPage.qml
@@ -47,17 +47,11 @@
property var addStickerPack: Kazv.AsyncHandler {
id: addStickerPack
trigger: () => {
- const type = Helpers.roomImagePackEventType;
- const stateKey = stickerPackStateKey.text;
- const state = room.state(type, stateKey);
- const content = state.content;
- content.pack = content.pack || {};
- content.pack.display_name = stickerPackName.text;
- return roomStickerPacksPage.room.sendStateEvent({
- type,
- state_key: stateKey,
- content,
- });
+ return matrixSession.addRoomStickerPack(
+ room.roomId,
+ stickerPackStateKey.text,
+ stickerPackName.text,
+ );
}
onResolved: (success, data) => {
diff --git a/src/js/matrix-helpers.js b/src/js/matrix-helpers.js
--- a/src/js/matrix-helpers.js
+++ b/src/js/matrix-helpers.js
@@ -125,5 +125,3 @@
}
const toolTipTimeout = 5000;
-const imagePackRoomsEventType = 'im.ponies.emote_rooms';
-const roomImagePackEventType = 'im.ponies.room_emotes';
diff --git a/src/matrix-session.hpp b/src/matrix-session.hpp
--- a/src/matrix-session.hpp
+++ b/src/matrix-session.hpp
@@ -233,6 +233,15 @@
*/
MatrixEvent *stickerRoomsEvent() const;
+ /**
+ * Update the sticker rooms for this account.
+ *
+ * @param content The content object for the sticker rooms account data event.
+ * @return A promise that resolves when the sticker rooms account data is updated,
+ * or when there is an error.
+ */
+ MatrixPromise *updateStickerRooms(const QJsonObject &content);
+
/**
* Update the sticker pack from source.
*
@@ -242,6 +251,17 @@
*/
MatrixPromise *updateStickerPack(MatrixStickerPackSource source);
+ /**
+ * Create a new sticker pack in a room.
+ *
+ * @param roomId The id of the room.
+ * @param stateKey The state key of the pack.
+ * @param displayName Thi display name of the pack.
+ * @return A promise that resolves when the sticker pack is added,
+ * or when there is an error.
+ */
+ MatrixPromise *addRoomStickerPack(const QString &roomId, const QString &stateKey, const QString &displayName);
+
MatrixUserGivenAttrsMap *userGivenNicknameMap() const;
MatrixPromise *sendAccountData(const QString &type, const QJsonObject &content);
diff --git a/src/matrix-session.cpp b/src/matrix-session.cpp
--- a/src/matrix-session.cpp
+++ b/src/matrix-session.cpp
@@ -447,7 +447,25 @@
MatrixEvent *MatrixSession::stickerRoomsEvent() const
{
- return new MatrixEvent(m_clientOnSecondaryRoot.accountData()[imagePackRoomsEventType][lager::lenses::or_default]);
+ return new MatrixEvent(m_clientOnSecondaryRoot.accountData().map(getCanonicalImagePackRoomsEvent));
+}
+
+MatrixPromise *MatrixSession::updateStickerRooms(const QJsonObject &content)
+{
+ auto promise = m_context.createResolvedPromise({});
+ for (const auto &type : imagePackRoomsEventTypes) {
+ auto event = Event(json{
+ {"type", type},
+ {"content", content},
+ });
+ promise = promise.then([client=m_clientOnSecondaryRoot.toEventLoop(), event, ctx=m_context](const auto &stat) {
+ if (stat.success()) {
+ return client.setAccountData(event);
+ }
+ return ctx.createResolvedPromise(stat);
+ });
+ }
+ return new MatrixPromise(promise);
}
MatrixPromise *MatrixSession::updateStickerPack(MatrixStickerPackSource source)
@@ -457,18 +475,49 @@
eventJson["type"] = source.eventType;
return sendAccountDataImpl(Event(std::move(eventJson)));
} else if (source.source == MatrixStickerPackSource::RoomState) {
- auto eventJson = std::move(source.event).raw().get();
- eventJson["type"] = source.eventType;
- eventJson["state_key"] = source.stateKey;
- return new MatrixPromise(
- m_clientOnSecondaryRoot
- .room(source.roomId)
- .sendStateEvent(Event(std::move(eventJson))));
+ auto room = m_clientOnSecondaryRoot
+ .room(source.roomId);
+ auto promise = m_context.createResolvedPromise({});
+ for (const auto &type : roomStateEventTypes) {
+ auto eventJson = std::move(source.event).raw().get();
+ eventJson["type"] = type;
+ eventJson["state_key"] = source.stateKey;
+ promise = promise.then([room=room.toEventLoop(), eventJson, ctx=m_context](const auto &stat) {
+ if (stat.success()) {
+ return room.sendStateEvent(Event(eventJson));
+ }
+ return ctx.createResolvedPromise(stat);
+ });
+ }
+
+ return new MatrixPromise(promise);
} else {
return 0;
}
}
+MatrixPromise *MatrixSession::addRoomStickerPack(const QString &roomId, const QString &stateKey, const QString &displayName)
+{
+ auto stateKeyStd = stateKey.toStdString();
+ auto roomIdStd = roomId.toStdString();
+ auto room = m_clientOnSecondaryRoot.room(roomIdStd);
+ auto eventJson = getCanonicalImagePackForRoom(room.stateEvents().make().get(), stateKeyStd).originalJson().get();
+ if (!eventJson.contains("content")) {
+ eventJson["content"] = json::object();
+ }
+ if (!eventJson["content"].contains("pack")) {
+ eventJson["content"]["pack"] = json::object();
+ }
+ eventJson["content"]["pack"]["display_name"] = displayName.toStdString();
+ return updateStickerPack(MatrixStickerPackSource{
+ MatrixStickerPackSource::RoomState,
+ roomStateEventTypes[0],
+ Event(eventJson),
+ roomIdStd,
+ stateKeyStd,
+ });
+}
+
MatrixUserGivenAttrsMap *MatrixSession::userGivenNicknameMap() const
{
return new MatrixUserGivenAttrsMap(
diff --git a/src/matrix-sticker-pack-list-p.hpp b/src/matrix-sticker-pack-list-p.hpp
--- a/src/matrix-sticker-pack-list-p.hpp
+++ b/src/matrix-sticker-pack-list-p.hpp
@@ -6,8 +6,24 @@
#pragma once
#include <kazv-defs.hpp>
+#include <event.hpp>
+#include <clientutil.hpp>
+#include <immer/array.hpp>
+#include <immer/map.hpp>
#include <string>
inline const std::string accountDataEventType = "im.ponies.user_emotes";
-inline const std::string roomStateEventType = "im.ponies.room_emotes";
-inline const std::string imagePackRoomsEventType = "im.ponies.emote_rooms";
+/// types for room state event image packs, primary then secondary
+inline const immer::array<std::string> roomStateEventTypes = {
+ "m.room.image_pack",
+ "im.ponies.room_emotes",
+};
+/// types for image pack rooms in account data, primary then secondary
+inline const immer::array<std::string> imagePackRoomsEventTypes = {
+ "m.image_pack.rooms",
+ "im.ponies.emote_rooms",
+};
+
+Kazv::Event getCanonicalImagePackRoomsEvent(immer::map<std::string, Kazv::Event> accountData);
+
+Kazv::Event getCanonicalImagePackForRoom(immer::map<Kazv::KeyOfState, Kazv::Event> state, const std::string &stateKey);
diff --git a/src/matrix-sticker-pack-list.cpp b/src/matrix-sticker-pack-list.cpp
--- a/src/matrix-sticker-pack-list.cpp
+++ b/src/matrix-sticker-pack-list.cpp
@@ -20,12 +20,45 @@
using ImagePackRoomMap = immer::map<std::string/* room id */, immer::map<std::string/* */, json>>;
+Event getCanonicalImagePackRoomsEvent(immer::map<std::string, Event> accountData)
+{
+ for (const auto &type: imagePackRoomsEventTypes) {
+ if (accountData.count(type)) {
+ return accountData[type];
+ }
+ }
+ return Event();
+}
+
+Event getCanonicalImagePackForRoom(immer::map<Kazv::KeyOfState, Kazv::Event> state, const std::string &stateKey)
+{
+ for (const auto &type: roomStateEventTypes) {
+ auto ks = KeyOfState{type, stateKey};
+ if (state.count(ks)) {
+ return state[ks];
+ }
+ }
+ return Event();
+}
+
+Event getCanonicalRoomPack(immer::map<KeyOfState, Event> evs, const std::string &stateKey)
+{
+ for (const auto &type: roomStateEventTypes) {
+ auto ks = KeyOfState{type, stateKey};
+ if (evs.count(ks)) {
+ return evs[ks];
+ }
+ }
+ return Event();
+}
+
lager::reader<immer::flex_vector<MatrixStickerPackSource>> getEventsFromClient(Client client)
{
lager::reader<Event> userEmotes = client.accountData()[accountDataEventType][lager::lenses::or_default];
return lager::with(
userEmotes,
- client.accountData()[imagePackRoomsEventType][lager::lenses::or_default]
+ client.accountData()
+ .map(getCanonicalImagePackRoomsEvent)
// The following jsonAtOr performs the validation for us:
// if the content does not conform to the string-to-string-to-anything map, return an empty one
.xform(eventContent | jsonAtOr("rooms", ImagePackRoomMap{})),
@@ -42,8 +75,8 @@
for (const auto &[stateKey, _] : stateKeyMap) {
res.push_back(MatrixStickerPackSource{
MatrixStickerPackSource::RoomState,
- roomStateEventType,
- rooms[roomId].stateEvents[KeyOfState{roomStateEventType, stateKey}],
+ roomStateEventTypes[0],
+ getCanonicalRoomPack(rooms[roomId].stateEvents, stateKey),
roomId,
stateKey,
});
@@ -60,13 +93,23 @@
.map([](const auto &roomId, const auto &state) {
return intoImmer(
immer::flex_vector<MatrixStickerPackSource>{},
- zug::filter([](const auto &pair) {
- return pair.first.type == roomStateEventType;
+ zug::filter([state](const auto &pair) {
+ auto it = std::find(roomStateEventTypes.begin(), roomStateEventTypes.end(), pair.first.type);
+ if (it == roomStateEventTypes.end()) {
+ return false;
+ }
+ // This is one of image pack types. Now check if it is the stable type
+ if (it == roomStateEventTypes.begin()) {
+ return true;
+ }
+ // Here, it is not a stable type.
+ // Only return true if there is no corresponding stable type for the same state key
+ return !state.count(KeyOfState{roomStateEventTypes[0], pair.first.stateKey});
})
| zug::map([roomId](const auto &pair) {
return MatrixStickerPackSource{
MatrixStickerPackSource::RoomState,
- roomStateEventType,
+ pair.first.type,
pair.second,
roomId,
pair.first.stateKey,
diff --git a/src/tests/matrix-sticker-pack-test.cpp b/src/tests/matrix-sticker-pack-test.cpp
--- a/src/tests/matrix-sticker-pack-test.cpp
+++ b/src/tests/matrix-sticker-pack-test.cpp
@@ -38,7 +38,9 @@
private Q_SLOTS:
void testStickerPack();
void testStickerPackList();
+ void testStickerPackListStable();
void testStickerPackListInRoom();
+ void testStickerPackListInRoomStable();
void testAddToPack();
void testRemoveFromPack();
};
@@ -82,7 +84,21 @@
"type": "im.ponies.emote_rooms"
})"_json);
-static Event getRoomStickersEvent(std::string stateKey, std::string name)
+static const auto imagePackRoomsEventStable = Event(R"({
+ "content": {
+ "rooms": {
+ "!someroom:example.org": {
+ "de.sorunome.mx-puppet-bridge.discord": {}
+ },
+ "!someotherroom:example.org": {
+ "": {}
+ }
+ }
+ },
+ "type": "im.ponies.emote_rooms"
+})"_json);
+
+static Event getRoomStickersEvent(std::string stateKey, std::string name, bool stable = false)
{
auto j = R"({
"content": {
@@ -105,6 +121,9 @@
},
"type": "im.ponies.room_emotes"
})"_json;
+ if (stable) {
+ j["type"] = "m.room.image_pack";
+ }
j["state_key"] = stateKey;
j["content"]["pack"]["display_name"] = name;
return Event(j);
@@ -212,7 +231,7 @@
{u"source"_s, MatrixStickerPackSource::RoomState},
{u"isAccountData"_s, false},
{u"isState"_s, true},
- {u"eventType"_s, u"im.ponies.room_emotes"_s},
+ {u"eventType"_s, u"m.room.image_pack"_s},
{u"roomId"_s, u"!someroom:example.org"_s},
{u"stateKey"_s, u""_s},
{u"packName"_s, u"Pack 1"_s},
@@ -221,7 +240,7 @@
{u"source"_s, MatrixStickerPackSource::RoomState},
{u"isAccountData"_s, false},
{u"isState"_s, true},
- {u"eventType"_s, u"im.ponies.room_emotes"_s},
+ {u"eventType"_s, u"m.room.image_pack"_s},
{u"roomId"_s, u"!someroom:example.org"_s},
{u"stateKey"_s, u"de.sorunome.mx-puppet-bridge.discord"_s},
{u"packName"_s, u"Pack 2"_s},
@@ -230,7 +249,7 @@
{u"source"_s, MatrixStickerPackSource::RoomState},
{u"isAccountData"_s, false},
{u"isState"_s, true},
- {u"eventType"_s, u"im.ponies.room_emotes"_s},
+ {u"eventType"_s, u"m.room.image_pack"_s},
{u"roomId"_s, u"!someotherroom:example.org"_s},
{u"stateKey"_s, u""_s},
{u"packName"_s, u"Pack 3"_s},
@@ -242,7 +261,7 @@
auto p1 = toUniquePtr(stickerPackList->packFor(QJsonObject{
{u"source"_s, MatrixStickerPackSource::RoomState},
- {u"eventType"_s, u"im.ponies.room_emotes"_s},
+ {u"eventType"_s, u"m.room.image_pack"_s},
{u"roomId"_s, u"!someroom:example.org"_s},
{u"stateKey"_s, u""_s},
}));
@@ -250,13 +269,47 @@
auto p2 = toUniquePtr(stickerPackList->packFor(QJsonObject{
{u"source"_s, MatrixStickerPackSource::RoomState},
- {u"eventType"_s, u"im.ponies.room_emotes"_s},
+ {u"eventType"_s, u"m.room.image_pack"_s},
{u"roomId"_s, u"!someotherroom:example.org"_s},
{u"stateKey"_s, u"somestatekey"_s},
}));
QVERIFY(p2->isAccountData());
}
+void MatrixStickerPackTest::testStickerPackListStable()
+{
+ auto model = makeClient(
+ withAccountData({stickerPackEvent, imagePackRoomsEvent, imagePackRoomsEventStable})
+ | withRoom(makeRoom(
+ withRoomId("!someroom:example.org")
+ | withRoomState({
+ getRoomStickersEvent("", "Pack 1"),
+ getRoomStickersEvent("de.sorunome.mx-puppet-bridge.discord", "Pack 2"),
+ getRoomStickersEvent("de.sorunome.mx-puppet-bridge.discord", "Pack 2 stable", /* stable = */ true),
+ })
+ ))
+ | withRoom(makeRoom(
+ withRoomId("!someotherroom:example.org")
+ | withRoomState({getRoomStickersEvent("", "Pack 3")})
+ ))
+ );
+ SessionSetup s(SdkModel{model});
+ auto stickerPackList = toUniquePtr(s.session.stickerPackList());
+
+ // stable types takes over unstable types
+ QCOMPARE(stickerPackList->rowCount(QModelIndex()), 3);
+ QCOMPARE(stickerPackList->count(), 3);
+
+ auto packs = std::array<std::unique_ptr<MatrixStickerPack>, 3>{
+ toUniquePtr(stickerPackList->at(0)),
+ toUniquePtr(stickerPackList->at(1)),
+ toUniquePtr(stickerPackList->at(2)),
+ };
+
+ QVERIFY(hasPack(packs, u"Pack 2 stable"_s));
+ QVERIFY(!hasPack(packs, u"Pack 2"_s));
+}
+
void MatrixStickerPackTest::testStickerPackListInRoom()
{
auto model = makeClient(
@@ -307,6 +360,34 @@
QCOMPARE(QSet<QJsonValue>(packsArr.begin(), packsArr.end()), expectedPacks);
}
+void MatrixStickerPackTest::testStickerPackListInRoomStable()
+{
+ auto model = makeClient(
+ withRoom(makeRoom(
+ withRoomId("!someroom:example.org")
+ | withRoomState({
+ getRoomStickersEvent("", "Pack 1"),
+ getRoomStickersEvent("de.sorunome.mx-puppet-bridge.discord", "Pack 2"),
+ getRoomStickersEvent("de.sorunome.mx-puppet-bridge.discord", "Pack 2 stable", /* stable = */ true),
+ })
+ ))
+ );
+ SessionSetup s(SdkModel{model});
+ auto roomList = toUniquePtr(s.session.roomList());
+ auto room = toUniquePtr(roomList->room(u"!someroom:example.org"_s));
+ auto stickerPackList = toUniquePtr(room->stickerPackList());
+ QCOMPARE(stickerPackList->count(), 2);
+
+ auto packs = std::array<std::unique_ptr<MatrixStickerPack>, 2>{
+ toUniquePtr(stickerPackList->at(0)),
+ toUniquePtr(stickerPackList->at(1)),
+ };
+
+ QVERIFY(hasPack(packs, u"Pack 1"_s));
+ QVERIFY(hasPack(packs, u"Pack 2 stable"_s));
+ QVERIFY(!hasPack(packs, u"Pack 2"_s));
+}
+
void MatrixStickerPackTest::testAddToPack()
{
using namespace nlohmann::literals;
diff --git a/src/tests/quick-tests/test-helpers/MatrixSessionMock.qml b/src/tests/quick-tests/test-helpers/MatrixSessionMock.qml
--- a/src/tests/quick-tests/test-helpers/MatrixSessionMock.qml
+++ b/src/tests/quick-tests/test-helpers/MatrixSessionMock.qml
@@ -25,6 +25,8 @@
])
property var joinRoom: mockHelper.promise()
property var sendAccountData: mockHelper.promise()
+ property var updateStickerRooms: mockHelper.promise()
+ property var addRoomStickerPack: mockHelper.promise()
property var login: mockHelper.noop()
property var ssoLoginStart: mockHelper.func((serverUrl) => serverUrl + '/_matrix/client/v3/login/sso/redirect?redirectUrl=http://127.0.0.1:7456/sso-redirect/random')
property var discoverAndGetLoginFlows: mockHelper.noop()
diff --git a/src/tests/quick-tests/tst_RoomStickerPackItemDelegate.qml b/src/tests/quick-tests/tst_RoomStickerPackItemDelegate.qml
--- a/src/tests/quick-tests/tst_RoomStickerPackItemDelegate.qml
+++ b/src/tests/quick-tests/tst_RoomStickerPackItemDelegate.qml
@@ -45,9 +45,9 @@
const usePackAction = findChild(packItem, 'usePackAction');
verify(!usePackAction.checked);
usePackAction.trigger();
- tryVerify(() => matrixSession.sendAccountData.calledTimes() === 1);
+ tryVerify(() => matrixSession.updateStickerRooms.calledTimes() === 1);
verify(JsHelpers.deepEqual(
- matrixSession.sendAccountData.lastArgs()[1],
+ matrixSession.updateStickerRooms.lastArgs()[0],
{
rooms: {
'!foo:example.com': {
@@ -72,9 +72,9 @@
const usePackAction = findChild(packItem, 'usePackAction');
verify(usePackAction.checked);
usePackAction.trigger();
- tryVerify(() => matrixSession.sendAccountData.calledTimes() === 1);
+ tryVerify(() => matrixSession.updateStickerRooms.calledTimes() === 1);
verify(JsHelpers.deepEqual(
- matrixSession.sendAccountData.lastArgs()[1],
+ matrixSession.updateStickerRooms.lastArgs()[0],
{
rooms: {
'!foo:example.com': {
diff --git a/src/tests/quick-tests/tst_RoomStickerPacksPage.qml b/src/tests/quick-tests/tst_RoomStickerPacksPage.qml
--- a/src/tests/quick-tests/tst_RoomStickerPacksPage.qml
+++ b/src/tests/quick-tests/tst_RoomStickerPacksPage.qml
@@ -55,42 +55,18 @@
{
succ: true,
stateKey: '',
- packContent: {
- pack: {
- display_name: 'some name',
- },
- },
},
{
succ: false,
stateKey: '',
- packContent: {
- pack: {
- display_name: 'some name',
- },
- },
},
{
succ: true,
stateKey: 'foo',
- packContent: {
- images: {
- 'mew': {},
- },
- pack: {
- display_name: 'some name',
- },
- },
},
{
succ: true,
stateKey: 'bar',
- packContent: {
- pack: {
- 'some': 'others',
- display_name: 'some name',
- },
- },
},
];
}
@@ -101,17 +77,17 @@
findChild(page, 'stickerPackName').text = 'some name';
findChild(page, 'stickerPackStateKey').text = data.stateKey;
page.addStickerPackPopup.accept();
- tryVerify(() => page.room.sendStateEvent.calledTimes() === 1);
+ tryVerify(() => matrixSession.addRoomStickerPack.calledTimes() === 1);
verify(JsHelpers.deepEqual(
- page.room.sendStateEvent.lastArgs(),
- [{
- type: MatrixHelpers.roomImagePackEventType,
- state_key: data.stateKey,
- content: data.packContent,
- }],
+ matrixSession.addRoomStickerPack.lastArgs(),
+ [
+ page.room.roomId,
+ data.stateKey,
+ 'some name',
+ ],
));
- page.room.sendStateEvent.lastRetVal().resolve(data.succ, {});
+ matrixSession.addRoomStickerPack.lastRetVal().resolve(data.succ, {});
compare(item.showPassiveNotification.calledTimes(), 1);
}
}

File Metadata

Mime Type
text/plain
Expires
Fri, Aug 7, 3:17 PM (20 h, 6 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1723102
Default Alt Text
D341.1786141036.diff (21 KB)

Event Timeline