Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F113959
D166.1732499635.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
9 KB
Referenced Files
None
Subscribers
None
D166.1732499635.diff
View Options
diff --git a/src/contents/ui/StickerPicker.qml b/src/contents/ui/StickerPicker.qml
--- a/src/contents/ui/StickerPicker.qml
+++ b/src/contents/ui/StickerPicker.qml
@@ -17,35 +17,29 @@
id: stickerPicker
property var stickerPackList
spacing: 0
+ property var currentIndex: 0
signal sendMessageRequested(var eventJson)
- ScrollView {
- id: packListScrollView
+ TabBar {
+ id: packListView
Layout.fillWidth: true
Layout.minimumHeight: Kirigami.Units.gridUnit * 2
- Layout.preferredHeight: packListView.height
-
- ListView {
- id: packListView
- orientation: ListView.Horizontal
- height: contentHeight
- anchors.fill: parent
- currentIndex: 0
+ Repeater {
model: stickerPackList
- delegate: ToolButton {
+ delegate: TabButton {
objectName: `stickerPack${index}`
property var pack: stickerPackList.at(index)
icon.name: 'smiley'
- text: l10n.get('sticker-picker-user-stickers')
- checked: ListView.currentIndex === index
- onClicked: ListView.currentIndex = index
+ text: pack.packName ? pack.packName : l10n.get('sticker-picker-user-stickers')
+ checked: stickerPicker.currentIndex === index
+ onClicked: stickerPicker.currentIndex = index
}
}
}
- property var currentPack: packListView.currentItem && packListView.currentItem.pack
+ property var currentPack: stickerPackList.at(currentIndex)
property var stickerSize: Kirigami.Units.iconSizes.enormous
property var stickerMargin: Kirigami.Units.smallSpacing
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
@@ -15,15 +15,41 @@
using namespace Kazv;
static const std::string accountDataEventType = "im.ponies.user_emotes";
+static const std::string roomStateEventType = "im.ponies.room_emotes";
+static const std::string imagePackRoomsEventType = "im.ponies.emote_rooms";
+
+using ImagePackRoomMap = immer::map<std::string/* room id */, immer::map<std::string/* */, json>>;
lager::reader<immer::flex_vector<MatrixStickerPackSource>> getEventsFromClient(Client client)
{
lager::reader<Event> userEmotes = client.accountData()[accountDataEventType][lager::lenses::or_default];
- return userEmotes.map([](Event e) {
- return immer::flex_vector<MatrixStickerPackSource>{
- {MatrixStickerPackSource::AccountData, accountDataEventType, e},
- };
- });
+ return lager::with(
+ userEmotes,
+ client.accountData()[imagePackRoomsEventType][lager::lenses::or_default]
+ // 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{})),
+ client.rooms()).map([](
+ const Event &userEmotes,
+ const ImagePackRoomMap &emoteRooms,
+ const immer::map<std::string, RoomModel> &rooms) {
+ // This transformation function takes O(|room sticker packs specified in account data|).
+ auto res = immer::flex_vector<MatrixStickerPackSource>{
+ {MatrixStickerPackSource::AccountData, accountDataEventType, userEmotes}
+ }.transient();
+
+ for (const auto &[roomId, stateKeyMap] : emoteRooms) {
+ for (const auto &[stateKey, _] : stateKeyMap) {
+ res.push_back(MatrixStickerPackSource{
+ MatrixStickerPackSource::RoomState,
+ roomStateEventType,
+ rooms[roomId].stateEvents[KeyOfState{roomStateEventType, stateKey}]
+ });
+ }
+ }
+
+ return res.persistent();
+ }).make();
}
MatrixStickerPackList::MatrixStickerPackList(Client client, QObject *parent)
diff --git a/src/matrix-sticker-pack.hpp b/src/matrix-sticker-pack.hpp
--- a/src/matrix-sticker-pack.hpp
+++ b/src/matrix-sticker-pack.hpp
@@ -39,6 +39,8 @@
Q_INVOKABLE MatrixSticker *at(int index) const;
+ LAGER_QT_READER(QString, packName);
+
Q_INVOKABLE bool hasShortCode(const QString &shortCode) const;
/**
diff --git a/src/matrix-sticker-pack.cpp b/src/matrix-sticker-pack.cpp
--- a/src/matrix-sticker-pack.cpp
+++ b/src/matrix-sticker-pack.cpp
@@ -7,7 +7,7 @@
#include <kazv-defs.hpp>
#include <cursorutil.hpp>
-
+#include "helper.hpp"
#include "matrix-sticker.hpp"
#include "matrix-event.hpp"
#include "matrix-sticker-pack.hpp"
@@ -38,6 +38,7 @@
return json::array();
}
})))
+ , LAGER_QT(packName)(m_event.xform(eventContent | jsonAtOr("/pack/display_name"_json_pointer, std::string()) | strToQt))
{
initCountCursor(m_images.map([](const JsonWrap &images) -> int {
return images.get().size();
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
@@ -62,6 +62,49 @@
"type": "im.ponies.user_emotes"
})"_json};
+static const auto imagePackRoomsEvent = 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)
+{
+ auto j = R"({
+ "content": {
+ "images": {
+ "myemote": {
+ "url": "mxc://example.org/blah"
+ },
+ "mysticker": {
+ "body": "my sticker",
+ "url": "mxc://example.org/sticker",
+ "usage": ["sticker"],
+ "info": {
+ "mimetype": "image/png"
+ }
+ }
+ },
+ "pack": {
+ "usage": ["emoticon"]
+ }
+ },
+ "type": "im.ponies.room_emotes"
+})"_json;
+ j["state_key"] = stateKey;
+ j["pack"]["display_name"] = name;
+ return Event(j);
+}
+
void MatrixStickerPackTest::testStickerPack()
{
auto sourceCursor = lager::make_state(MatrixStickerPackSource{
@@ -108,15 +151,43 @@
void MatrixStickerPackTest::testStickerPackList()
{
- auto model = makeClient(withAccountData({stickerPackEvent}));
+ auto model = makeClient(
+ withAccountData({stickerPackEvent, imagePackRoomsEvent})
+ | withRoom(makeRoom(
+ withRoomId("!someroom:example.org")
+ | withRoomState({
+ getRoomStickersEvent("", "Pack 1"),
+ getRoomStickersEvent("de.sorunome.mx-puppet-bridge.discord", "Pack 2"),
+ })
+ ))
+ | withRoom(makeRoom(
+ withRoomId("!someotherroom:example.org")
+ | withRoomState({getRoomStickersEvent("", "Pack 3")})
+ ))
+ );
std::unique_ptr<MatrixSdk> sdk{makeTestSdk(SdkModel{model})};
auto stickerPackList = toUniquePtr(sdk->stickerPackList());
- QCOMPARE(stickerPackList->rowCount(QModelIndex()), 1);
- QCOMPARE(stickerPackList->count(), 1);
+ QCOMPARE(stickerPackList->rowCount(QModelIndex()), 4);
+ QCOMPARE(stickerPackList->count(), 4);
- auto stickerPack = toUniquePtr(stickerPackList->at(0));
- QCOMPARE(stickerPack->count(), 2);
+ auto packs = std::array<std::unique_ptr<MatrixStickerPack>, 4>{
+ toUniquePtr(stickerPackList->at(0)),
+ toUniquePtr(stickerPackList->at(1)),
+ toUniquePtr(stickerPackList->at(2)),
+ toUniquePtr(stickerPackList->at(3)),
+ };
+
+ auto hasPack = [&packs](const QString &name) {
+ return std::any_of(packs.begin(), packs.end(), [&name](const auto &pack) {
+ return pack->packName() == name;
+ });
+ };
+
+ QVERIFY(hasPack(u"Awesome Pack"_s));
+ QVERIFY(hasPack(u"Pack 1"_s));
+ QVERIFY(hasPack(u"Pack 2"_s));
+ QVERIFY(hasPack(u"Pack 3"_s));
}
void MatrixStickerPackTest::testAddToPack()
diff --git a/src/tests/quick-tests/tst_StickerPicker.qml b/src/tests/quick-tests/tst_StickerPicker.qml
--- a/src/tests/quick-tests/tst_StickerPicker.qml
+++ b/src/tests/quick-tests/tst_StickerPicker.qml
@@ -54,6 +54,26 @@
function at(index) {
return stickerPack0.get(index);
}
+ },
+ ListModel {
+ id: stickerPack1
+ ListElement {
+ shortCode: 'some2'
+ body: 'some2'
+ mxcUri: 'mxc://example.org/some2'
+ makeEventJson: () => makeSticker(stickerPack1.get(0))
+ }
+
+ ListElement {
+ shortCode: 'some3'
+ body: 'some3'
+ mxcUri: 'mxc://example.org/some3'
+ makeEventJson: () => makeSticker(stickerPack1.get(1))
+ }
+
+ function at(index) {
+ return stickerPack1.get(index);
+ }
}
]
@@ -68,6 +88,8 @@
id: stickerPackListModel
ListElement {
}
+ ListElement {
+ }
function at(index) {
return stickerPacks[index];
}
@@ -86,12 +108,19 @@
function test_stickerPicker() {
verify(findChild(stickerPicker, 'stickerPack0'));
+ verify(findChild(stickerPicker, 'stickerPack1'));
verify(findChild(stickerPicker, 'sticker0'));
verify(findChild(stickerPicker, 'sticker1'));
const stickerButton = findChild(stickerPicker, 'sticker1');
mouseClick(stickerButton);
- tryVerify(() => sendMessageRequestedSpy.count, 1000);
+ tryVerify(() => sendMessageRequestedSpy.count === 1, 1000);
verify(Helpers.deepEqual(sendMessageRequestedSpy.signalArguments[0][0], makeSticker(stickerPack0.get(1))));
+
+ mouseClick(findChild(stickerPicker, 'stickerPack1'));
+ tryVerify(() => findChild(stickerPicker, 'sticker0').sticker.mxcUri === 'mxc://example.org/some2');
+ mouseClick(findChild(stickerPicker, 'sticker0'));
+ tryVerify(() => sendMessageRequestedSpy.count === 2, 1000);
+ verify(Helpers.deepEqual(sendMessageRequestedSpy.signalArguments[1][0], makeSticker(stickerPack1.get(0))));
}
}
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Nov 24, 5:53 PM (11 h, 8 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
39981
Default Alt Text
D166.1732499635.diff (9 KB)
Attached To
Mode
D166: Support emote rooms in MSC2545
Attached
Detach File
Event Timeline
Log In to Comment