Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F85629787
D340.1786191545.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
D340.1786191545.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
@@ -21,6 +21,42 @@
signal sendMessageRequested(var eventJson)
+ property var removeStickerPack
+ property string removeStickerShortCode: ''
+
+ property var removeStickerHandler: Kazv.AsyncHandler {
+ trigger: () => {
+ return matrixSession.updateStickerPack(
+ stickerPicker.removeStickerPack.removeSticker(stickerPicker.removeStickerShortCode)
+ );
+ }
+ onResolved: (success, data) => {
+ if (!success) {
+ showPassiveNotification(l10n.get('sticker-remove-failed-prompt', { errorCode: data.errorCode, errorMsg: data.error }));
+ }
+ }
+ }
+
+ function requestRemoveSticker(pack, shortCode) {
+ stickerPicker.removeStickerPack = pack;
+ stickerPicker.removeStickerShortCode = shortCode;
+ removeStickerConfirmationComp.createObject(Overlay.overlay, {
+ message: l10n.get('sticker-remove-confirmation-message', { shortCode: shortCode })
+ }).open();
+ }
+
+ property var removeStickerConfirmationComp: Component {
+ Kazv.ConfirmationOverlay {
+ objectName: 'removeStickerConfirmation'
+ shouldSelfDestroy: true
+ title: l10n.get('sticker-remove-confirmation-title')
+ message: l10n.get('sticker-remove-confirmation-message')
+ confirmActionText: l10n.get('sticker-remove-confirm-action')
+ cancelActionText: l10n.get('sticker-remove-cancel-action')
+ onAccepted: stickerPicker.removeStickerHandler.call()
+ }
+ }
+
TabBar {
id: packListView
Layout.fillWidth: true
@@ -96,6 +132,16 @@
function requestSendMessage() {
stickerPicker.sendMessageRequested(sticker.makeEventJson());
}
+
+ ContextMenu.menu: Menu {
+ objectName: 'stickerContextMenu'
+ Kirigami.Action {
+ objectName: 'removeStickerMenuItem'
+ text: l10n.get('sticker-remove-action')
+ icon.name: 'edit-delete'
+ onTriggered: stickerPicker.requestRemoveSticker(currentPack, sticker.shortCode)
+ }
+ }
}
}
}
diff --git a/src/l10n/cmn-Hans/100-ui.ftl b/src/l10n/cmn-Hans/100-ui.ftl
--- a/src/l10n/cmn-Hans/100-ui.ftl
+++ b/src/l10n/cmn-Hans/100-ui.ftl
@@ -283,6 +283,13 @@
add-sticker-popup-cancel-button = 取消
add-sticker-popup-failed-prompt = 无法添加贴纸。错误代码:{ $errorCode }。错误讯息:{ $errorMsg }。
+sticker-remove-action = 移除贴纸...
+sticker-remove-confirmation-title = 移除贴纸
+sticker-remove-confirmation-message = 确定要移除贴纸「{ $shortCode }」吗?
+sticker-remove-confirm-action = 移除
+sticker-remove-cancel-action = 不移除
+sticker-remove-failed-prompt = 无法移除贴纸。错误代码:{ $errorCode }。错误讯息:{ $errorMsg }。
+
kazv-io-download-success-prompt = 下载成功
kazv-io-download-failure-prompt = 下载失败:{ $detail }
kazv-io-failure-detail-user-cancel = 用户已取消
diff --git a/src/l10n/en/100-ui.ftl b/src/l10n/en/100-ui.ftl
--- a/src/l10n/en/100-ui.ftl
+++ b/src/l10n/en/100-ui.ftl
@@ -305,6 +305,13 @@
add-sticker-popup-cancel-button = Cancel
add-sticker-popup-failed-prompt = Unable to add sticker. Error code: { $errorCode }. Error message: { $errorMsg }.
+sticker-remove-action = Remove sticker...
+sticker-remove-confirmation-title = Remove sticker
+sticker-remove-confirmation-message = Are you sure you want to remove the sticker "{ $shortCode }"?
+sticker-remove-confirm-action = Remove
+sticker-remove-cancel-action = Do not remove
+sticker-remove-failed-prompt = Unable to remove sticker. Error code: { $errorCode }. Error message: { $errorMsg }.
+
kazv-io-download-success-prompt = Download successful
kazv-io-download-failure-prompt = Download failure: { $detail }
kazv-io-failure-detail-user-cancel = User canceled
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
@@ -56,4 +56,13 @@
* @return The MatrixStickerPackSource of the modified pack.
*/
Q_INVOKABLE QVariant addSticker(const QString &shortCode, MatrixEvent *event) const;
+
+ /**
+ * Remove a sticker from the pack by short code and return the
+ * source of the modified pack.
+ *
+ * @param shortCode The short code of the sticker to remove.
+ * @return The MatrixStickerPackSource of the modified pack.
+ */
+ Q_INVOKABLE QVariant removeSticker(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
@@ -121,3 +121,18 @@
return QVariant::fromValue(source);
}
+
+QVariant MatrixStickerPack::removeSticker(const QString &shortCode) const
+{
+ auto source = m_source.get();
+
+ auto eventJson = source.event.raw().get();
+ if (eventJson.contains("/content/images"_json_pointer)
+ && eventJson["content"]["images"].is_object()) {
+ eventJson["content"]["images"].erase(shortCode.toStdString());
+ }
+
+ source.event = Event(eventJson);
+
+ return QVariant::fromValue(source);
+}
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -99,6 +99,7 @@
tst_SendMessageBoxDrafts.qml
tst_SendMessageBox.qml
tst_StickerPackNameProvider.qml
+ tst_StickerPicker.qml
tst_TypingIndicator.qml
tst_UserNameProvider.qml
tst_UserPage.qml
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
@@ -40,6 +40,7 @@
void testStickerPackList();
void testStickerPackListInRoom();
void testAddToPack();
+ void testRemoveFromPack();
};
// https://github.com/Sorunome/matrix-doc/blob/soru/emotes/proposals/2545-emotes.md
@@ -338,6 +339,31 @@
QVERIFY(newSource.event.content().get() == expected);
}
+void MatrixStickerPackTest::testRemoveFromPack()
+{
+ auto sourceCursor = lager::make_state(MatrixStickerPackSource{
+ MatrixStickerPackSource::AccountData,
+ "im.ponies.user_emotes",
+ stickerPackEvent,
+ "",
+ "",
+ }, lager::automatic_tag{});
+
+ auto stickerPack = toUniquePtr(new MatrixStickerPack(sourceCursor));
+
+ auto newSource = stickerPack->removeSticker(u"myemote"_s).template value<MatrixStickerPackSource>();
+
+ auto expected = sourceCursor.get().event.content().get();
+ expected["images"].erase("myemote");
+
+ QVERIFY(newSource.event.content().get() == expected);
+ QVERIFY(!newSource.event.content().get()["images"].contains("myemote"));
+
+ // Removing a non-existent sticker should leave the pack unchanged.
+ auto unchangedSource = stickerPack->removeSticker(u"doesnotexist"_s).template value<MatrixStickerPackSource>();
+ QVERIFY(unchangedSource.event.content().get() == sourceCursor.get().event.content().get());
+}
+
QTEST_MAIN(MatrixStickerPackTest)
#include "matrix-sticker-pack-test.moc"
diff --git a/src/tests/quick-tests/tst_StickerPicker.qml b/src/tests/quick-tests/tst_StickerPicker.qml
new file mode 100644
--- /dev/null
+++ b/src/tests/quick-tests/tst_StickerPicker.qml
@@ -0,0 +1,82 @@
+/*
+ * This file is part of kazv.
+ * SPDX-FileCopyrightText: 2026 tusooa <tusooa@kazv.moe>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+import QtQuick 2.15
+import QtQuick.Layouts 1.15
+import QtQuick.Window
+import QtQuick.Controls
+import QtTest 1.0
+
+import '../../contents/ui' as Kazv
+import 'test-helpers.js' as JsHelpers
+import 'test-helpers' as QmlHelpers
+
+QmlHelpers.TestItem {
+ id: item
+
+ property var someShortCode: 'myemote'
+
+ property var somePack: ListModel {
+ id: somePack
+ property string packName: 'Pack 0'
+ function removeSticker(shortCode) {
+ return { _removedShortCode: shortCode };
+ }
+ function at(index) {
+ return null;
+ }
+ }
+
+ Kazv.StickerPicker {
+ id: stickerPicker
+ anchors.fill: parent
+ stickerPackList: ListModel {
+ id: stickerPackListModel
+ ListElement {}
+ function at(index) {
+ return somePack;
+ }
+ }
+ }
+
+ TestCase {
+ id: stickerPickerTest
+ name: 'StickerPickerTest'
+ when: windowShown
+
+ function init() {
+ mockHelper.clearAll();
+ }
+
+ function _openConfirmation() {
+ stickerPicker.requestRemoveSticker(somePack, item.someShortCode);
+ const popup = findChild(Overlay.overlay, 'removeStickerConfirmation');
+ verify(popup);
+ tryVerify(() => popup.opened);
+ return popup;
+ }
+
+ function test_removeStickerConfirm() {
+ const popup = _openConfirmation();
+ mouseClick(findChild(popup, 'confirmButton'));
+ verify(matrixSession.updateStickerPack.calledTimes() === 1);
+ verify(JsHelpers.deepEqual(matrixSession.updateStickerPack.lastArgs()[0], { _removedShortCode: item.someShortCode }));
+ tryVerify(() => !popup.opened);
+ tryVerify(() => !findChild(Overlay.overlay, 'removeStickerConfirmation'));
+ compare(showPassiveNotification.calledTimes(), 0);
+ }
+
+ function test_removeStickerFailure() {
+ const popup = _openConfirmation();
+ mouseClick(findChild(popup, 'confirmButton'));
+ verify(matrixSession.updateStickerPack.calledTimes() === 1);
+ tryVerify(() => !popup.opened);
+ matrixSession.updateStickerPack.lastRetVal().resolve(false, { errorCode: 'M_FORBIDDEN', error: 'no' });
+ compare(showPassiveNotification.calledTimes(), 1);
+ compare(showPassiveNotification.lastArgs()[0], l10n.get('sticker-remove-failed-prompt', { errorCode: 'M_FORBIDDEN', errorMsg: 'no' }));
+ }
+ }
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Aug 8, 5:19 AM (15 h, 3 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1722720
Default Alt Text
D340.1786191545.diff (9 KB)
Attached To
Mode
D340: Support removing stickers
Attached
Detach File
Event Timeline
Log In to Comment