| author | Stephen Paul Weber
<singpolyma@singpolyma.net> 2023-11-30 00:41:29 UTC |
| committer | Stephen Paul Weber
<singpolyma@singpolyma.net> 2023-12-11 15:59:52 UTC |
| parent | c959e8f6f318effe4ca6cbe2b181bae10ac67d2d |
| xmpp/Chat.hx | +22 | -4 |
| xmpp/Client.hx | +4 | -3 |
| xmpp/Presence.hx | +3 | -1 |
| xmpp/persistence/browser.js | +20 | -15 |
diff --git a/xmpp/Chat.hx b/xmpp/Chat.hx index 1b42a08..93bfef4 100644 --- a/xmpp/Chat.hx +++ b/xmpp/Chat.hx @@ -127,7 +127,7 @@ abstract class Chat { presence.caps = caps; setPresence(resource, presence); } else { - setPresence(resource, new Presence(caps)); + setPresence(resource, new Presence(caps, null)); } } @@ -398,7 +398,7 @@ class Channel extends Chat { override public function setPresence(resource:String, presence:Presence) { super.setPresence(resource, presence); - if (!inSync && resource == client.displayName()) { + if (!inSync && presence?.mucUser?.allTags("status").find((status) -> status.attr.get("code") == "110") != null) { persistence.lastId(client.accountId(), chatId, doSync); } } @@ -452,11 +452,29 @@ class Channel extends Chat { } override public function livePresence() { - return presence.exists(client.displayName()); + for (nick => p in presence) { + for (status in p?.mucUser?.allTags("status") ?? []) { + if (status.attr.get("code") == "110") { + return true; + } + } + } + return false; + } + + private function nickInUse() { + for (nick => p in presence) { + for (status in p?.mucUser?.allTags("status") ?? []) { + if (status.attr.get("code") == "110") { + return nick; + } + } + } + return client.displayName(); } private function getFullJid() { - return JID.parse(chatId).withResource(client.displayName()); + return JID.parse(chatId).withResource(nickInUse()); } public function getParticipants() { diff --git a/xmpp/Client.hx b/xmpp/Client.hx index dde8942..a46ab8b 100644 --- a/xmpp/Client.hx +++ b/xmpp/Client.hx @@ -297,6 +297,7 @@ class Client extends xmpp.EventEmitter { stream.on("presence", function(event) { final stanza:Stanza = event.stanza; final c = stanza.getChild("c", "http://jabber.org/protocol/caps"); + final mucUser = stanza.getChild("x", "http://jabber.org/protocol/muc#user"); if (stanza.attr.get("from") != null && stanza.attr.get("type") == null) { final from = JID.parse(stanza.attr.get("from")); final chat = getChat(from.asBare().asString()); @@ -305,7 +306,7 @@ class Client extends xmpp.EventEmitter { return EventUnhandled; } if (c == null) { - chat.setCaps(JID.parse(stanza.attr.get("from")).resource, null); + chat.setPresence(JID.parse(stanza.attr.get("from")).resource, new Presence(null, mucUser)); persistence.storeChat(jid, chat); if (chat.livePresence()) this.trigger("chats/update", [chat]); } else { @@ -313,14 +314,14 @@ class Client extends xmpp.EventEmitter { if (caps == null) { final discoGet = new DiscoInfoGet(stanza.attr.get("from"), c.attr.get("node") + "#" + c.attr.get("ver")); discoGet.onFinished(() -> { - chat.setCaps(JID.parse(stanza.attr.get("from")).resource, discoGet.getResult()); + chat.setPresence(JID.parse(stanza.attr.get("from")).resource, new Presence(discoGet.getResult(), mucUser)); if (discoGet.getResult() != null) persistence.storeCaps(discoGet.getResult()); persistence.storeChat(jid, chat); if (chat.livePresence()) this.trigger("chats/update", [chat]); }); sendQuery(discoGet); } else { - chat.setCaps(JID.parse(stanza.attr.get("from")).resource, caps); + chat.setPresence(JID.parse(stanza.attr.get("from")).resource, new Presence(caps, mucUser)); persistence.storeChat(jid, chat); if (chat.livePresence()) this.trigger("chats/update", [chat]); } diff --git a/xmpp/Presence.hx b/xmpp/Presence.hx index fe25e63..5ea29bb 100644 --- a/xmpp/Presence.hx +++ b/xmpp/Presence.hx @@ -3,8 +3,10 @@ package xmpp; @:expose class Presence { public var caps:Null<Caps>; + public var mucUser:Null<Stanza>; - public function new(caps: Null<Caps>) { + public function new(caps: Null<Caps>, mucUser: Null<Stanza>) { this.caps = caps; + this.mucUser = mucUser; } } diff --git a/xmpp/persistence/browser.js b/xmpp/persistence/browser.js index 4ebb5b4..f10b21b 100644 --- a/xmpp/persistence/browser.js +++ b/xmpp/persistence/browser.js @@ -167,7 +167,7 @@ exports.xmpp.persistence = { chatId: chat.chatId, trusted: chat.trusted, avatarSha1: chat.avatarSha1, - presence: chat.presence, + presence: Object.fromEntries(Object.entries(chat.presence || {}).map(([k, p]) => [k, { caps: p.caps?.ver(), mucUser: p.mucUser?.toString() }])), displayName: chat.displayName, uiState: chat.uiState?.toString(), extensions: chat.extensions?.toString(), @@ -177,20 +177,25 @@ exports.xmpp.persistence = { }, getChats: function(account, callback) { - const tx = db.transaction(["chats"], "readonly"); - const store = tx.objectStore("chats"); - const range = IDBKeyRange.bound([account], [account, []]); - promisifyRequest(store.getAll(range)).then((result) => callback(result.map((r) => new xmpp.SerializedChat( - r.chatId, - r.trusted, - r.avatarSha1, - r.presence, - r.displayName, - r.uiState, - r.extensions, - r.disco, - r.class - )))); + (async () => { + const tx = db.transaction(["chats"], "readonly"); + const store = tx.objectStore("chats"); + const range = IDBKeyRange.bound([account], [account, []]); + const result = await promisifyRequest(store.getAll(range)); + return await Promise.all(result.map(async (r) => new xmpp.SerializedChat( + r.chatId, + r.trusted, + r.avatarSha1, + Object.fromEntries(await Promise.all(Object.entries(r.presence).map( + async ([k, p]) => [k, new xmpp.Presence(p.caps && await new Promise((resolve) => this.getCaps(p.caps, resolve)), p.mucUser && xmpp.Stanza.parse(p.mucUser))] + ))), + r.displayName, + r.uiState, + r.extensions, + r.disco, + r.class + ))); + })().then(callback); }, getChatsUnreadDetails: function(account, chatsArray, callback) {