From b87c8356bc1b6263345b02bc8bfca8d2d73d83c7 Mon Sep 17 00:00:00 2001 From: Nick Jennings Date: Sun, 11 Oct 2026 16:14:54 +0200 Subject: [PATCH] fix: keep the channel user list tracked after an attendance reply updateChannelUserList replaced the TrackedArray with the plain members array from the response. Later join and leave updates mutated that plain array, so the sidebar stopped re-rendering. Sockethub now answers IRC attendance queries with the same single members message as XMPP (sockethub/sockethub#1308), which made this reachable on IRC too. --- app/services/coms.js | 3 ++- tests/unit/services/coms-test.js | 29 +++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/app/services/coms.js b/app/services/coms.js index ca1c7c62..340f57bb 100644 --- a/app/services/coms.js +++ b/app/services/coms.js @@ -207,7 +207,8 @@ export default class ComsService extends Service { if (channel) { channel.connected = true; if (Array.isArray(message.object.members)) { - channel.userList = message.object.members; + // Keep the list tracked, so later join/leave updates re-render. + channel.userList = new TrackedArray(message.object.members); } } } diff --git a/tests/unit/services/coms-test.js b/tests/unit/services/coms-test.js index e929f089..a40b9fd4 100644 --- a/tests/unit/services/coms-test.js +++ b/tests/unit/services/coms-test.js @@ -3,6 +3,7 @@ import { setupTest } from 'ember-qunit'; import sinon from 'sinon'; import Channel from 'hyperchannel/models/channel'; import Message from 'hyperchannel/models/message'; +import { TrackedArray } from 'tracked-built-ins'; import { ircAccount, xmppAccount } from '../../fixtures/accounts'; function jsonResponse (body) { @@ -117,6 +118,34 @@ module('Unit | Service | coms', function (hooks) { assert.ok(channel.connected); assert.strictEqual(channel.userList.length, 5); + assert.ok(channel.userList instanceof TrackedArray, 'user list stays tracked'); + }); + + test('#updateChannelUserList accepts the IRC attendance response', function (assert) { + const channel = new Channel({ + account: ircAccount, + name: '#kosmos', + connected: false + }); + + const service = this.owner.factoryFor('service:coms').create({ + accounts: [ ircAccount ], + channels: [ channel ] + }); + + service.updateChannelUserList({ + type: 'query', + actor: { id: '#kosmos@irc.libera.chat', type: 'room', name: '#kosmos' }, + target: { id: 'jimmy@irc.libera.chat', type: 'person', name: 'jimmy' }, + object: { + type: 'attendance', + members: [ 'raucao', 'galfert', 'jimmy' ], + roles: { raucao: 'owner' } + } + }); + + assert.ok(channel.connected); + assert.deepEqual([...channel.userList], [ 'raucao', 'galfert', 'jimmy' ]); }); test('#updateChannelTopic sets the channel topic from the object content', function (assert) {