git » sdk » commit 47acfe2

Allow setting tags on chats

author Eric Roberts
2026-08-17 17:34:55 UTC
committer Stephen Paul Weber
2026-08-17 17:39:17 UTC
parent 00bfc804d50c1439935d64e58e27119bda5cf029

Allow setting tags on chats

Updated DirectChat to copy groups from extensions after we added the tags to
the extensions in setTags

borogove/Chat.hx +23 -4
test/TestChat.hx +38 -0

diff --git a/borogove/Chat.hx b/borogove/Chat.hx
index db4e262..53dbff9 100644
--- a/borogove/Chat.hx
+++ b/borogove/Chat.hx
@@ -699,6 +699,18 @@ abstract class Chat extends EventEmitter {
 		return extensions.allTags("group", "jabber:iq:roster").map(g -> g.getText());
 	}
 
+	/**
+		Set tags on this Chat
+
+		@param tags The tags to set
+	 **/
+	public function setTags(tags: Array<String>) {
+		extensions.removeChildren("group", "jabber:iq:roster");
+		for (tag in tags) {
+			extensions.textTag("group", tag, { xmlns: "jabber:iq:roster" });
+		}
+	}
+
 	@:allow(borogove)
 	private function setThreadSubject(threadId: String, subject: String) {
 		this.threads.set(threadId, subject);
@@ -1394,11 +1406,18 @@ class DirectChat extends Chat {
 		if (displayName != null && displayName != "" && displayName != chatId) {
 			attr["name"] = displayName;
 		}
-		stream.sendIq(
-			new Stanza("iq", { type: "set" })
+		final stanza = new Stanza("iq", { type: "set" })
 				.tag("query", { xmlns: "jabber:iq:roster" })
-				.tag("item", attr)
-				.up().up(),
+				.tag("item", attr);
+
+		for (extension in extensions.allTags()) {
+			if (extension.name == "group" && extension.attr.get("xmlns") == "jabber:iq:roster") {
+				stanza.addChild(extension);
+			}
+		}
+
+		stream.sendIq(
+			stanza,
 			(response) -> {
 				if (response.attr.get("type") == "error") return;
 				stream.sendStanza(new Stanza("presence", { to: chatId, type: "subscribe", id: ID.unique() }));
diff --git a/test/TestChat.hx b/test/TestChat.hx
index 75745d3..f202710 100644
--- a/test/TestChat.hx
+++ b/test/TestChat.hx
@@ -17,6 +17,44 @@ import thenshim.Promise;
 
 @:access(borogove)
 class TestChat extends utest.Test {
+	public function testSetTags() {
+		final persistence = new Dummy();
+		final client = new Client("test@example.com", persistence);
+		final chat = client.getDirectChat("friend@example.com");
+
+		chat.setTags(["friends", "work"]);
+		Assert.same(["friends", "work"], chat.getTags());
+
+		chat.setTags(["family"]);
+		Assert.same(["family"], chat.getTags());
+	}
+
+	public function testDirectChatBookmarkIncludesTags(async: Async) {
+		final persistence = new Dummy();
+		final client = new Client("test@example.com", persistence);
+		final chat = client.getDirectChat("friend@example.com");
+		chat.setTags(["friends", "work"]);
+
+		client.stream.on("sendStanza", (stanza: Stanza) -> {
+			if (stanza.name == "iq" && stanza.attr.get("type") == "set") {
+				final query = stanza.getChild("query", "jabber:iq:roster");
+				Assert.notNull(query);
+
+				final item = query.getChild("item");
+				Assert.equals("friend@example.com", item.attr.get("jid"));
+				Assert.same(
+					["friends", "work"],
+					item.allTags("group", "jabber:iq:roster").map(group -> group.getText())
+				);
+				async.done();
+				return EventHandled;
+			}
+			return EventUnhandled;
+		});
+
+		chat.bookmark();
+	}
+
 	public function testGetMessagesBeforeNull(async: Async) {
 		final persistence = new Dummy();
 		final client = new Client("test@example.com", persistence);