quickblox 2.23.1 → 2.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/quickblox.js CHANGED
@@ -30502,7 +30502,8 @@ function filterStats(result, track, outbound) {
30502
30502
  var chatUtils = require('./qbChatHelpers'),
30503
30503
  config = require('../../qbConfig'),
30504
30504
  Utils = require('../../qbUtils'),
30505
- StreamManagement = require('../../plugins/streamManagement');
30505
+ StreamManagement = require('../../plugins/streamManagement'),
30506
+ noticeConsts = require('./qbNoticeConsts');
30506
30507
 
30507
30508
  var unsupportedError = 'This function isn\'t supported outside of the browser (...yet)';
30508
30509
 
@@ -30522,6 +30523,508 @@ if (Utils.getEnv().browser) {
30522
30523
  XMPP = require('node-xmpp-client');
30523
30524
  }
30524
30525
 
30526
+ // ============================================================================
30527
+ // Notice Feature parsing helpers (CROS-1055, SDK 2.24.0)
30528
+ // ----------------------------------------------------------------------------
30529
+ // Module-private. Used by ChatProxy._onSystemMessageListener to detect/parse
30530
+ // urn:xmpp:notice:0 stanzas. Pure functions — no instance state, easy to test
30531
+ // indirectly via chatProxy._onSystemMessageListener(stanza) call paths.
30532
+ //
30533
+ // Server contract reference: QuickBlox Confluence "Notice Feature" page
30534
+ // (https://quickblox.atlassian.net/wiki/spaces/CHAT/pages/4126081033) and
30535
+ // Android tests in android-reference-2026-05-07/test/.
30536
+ // ============================================================================
30537
+
30538
+ var NOTICE_KNOWN_MODULE_IDS = {};
30539
+ NOTICE_KNOWN_MODULE_IDS[noticeConsts.NOTICE_MODULE_IDENTIFIER.UPDATED_MESSAGE] = true;
30540
+ NOTICE_KNOWN_MODULE_IDS[noticeConsts.NOTICE_MODULE_IDENTIFIER.DELETED_MESSAGE] = true;
30541
+ NOTICE_KNOWN_MODULE_IDS[noticeConsts.NOTICE_MODULE_IDENTIFIER.UPDATED_DIALOG] = true;
30542
+ NOTICE_KNOWN_MODULE_IDS[noticeConsts.NOTICE_MODULE_IDENTIFIER.DELETED_DIALOG] = true;
30543
+
30544
+ /**
30545
+ * Cross-env: get all direct child elements of `parent` whose tag name equals
30546
+ * `name`. Works for browser DOM, xmldom, and ltx (node-xmpp-client).
30547
+ *
30548
+ * @param {Element|Object} parent
30549
+ * @param {String} name
30550
+ * @return {Array<Element|Object>}
30551
+ */
30552
+ function _getChildElements(parent, name) {
30553
+ if (!parent) {
30554
+ return [];
30555
+ }
30556
+ var out = [];
30557
+
30558
+ // Browser DOM / xmldom: walk childNodes filtering by nodeType and tagName.
30559
+ if (parent.childNodes && parent.childNodes.length !== undefined && typeof parent.childNodes !== 'function') {
30560
+ for (var i = 0; i < parent.childNodes.length; i++) {
30561
+ var c = parent.childNodes[i];
30562
+ if (!c || c.nodeType !== 1 /* ELEMENT_NODE */) {
30563
+ continue;
30564
+ }
30565
+ var tag = c.tagName || c.nodeName || c.localName;
30566
+ if (tag === name) {
30567
+ out.push(c);
30568
+ }
30569
+ }
30570
+ if (out.length > 0 || parent.childNodes.length > 0) {
30571
+ // Used DOM path (even if no matches) — return what we have.
30572
+ return out;
30573
+ }
30574
+ }
30575
+
30576
+ // ltx: `parent.children` is a mixed array of strings (text) and Element objects with `.name`.
30577
+ if (parent.children && parent.children.length !== undefined) {
30578
+ for (var j = 0; j < parent.children.length; j++) {
30579
+ var ch = parent.children[j];
30580
+ if (ch && typeof ch === 'object' && ch.name === name) {
30581
+ out.push(ch);
30582
+ }
30583
+ }
30584
+ }
30585
+
30586
+ return out;
30587
+ }
30588
+
30589
+ /**
30590
+ * Cross-env text reader for an Element node. In browser / xmldom uses
30591
+ * `textContent`; in node-xmpp-client (ltx) uses `getText()` or descends
30592
+ * into `.children` (mixed string/element children). Empty string treated
30593
+ * as no text, returns ''. Returns '' if element has no text at all.
30594
+ *
30595
+ * This is needed because the existing `chatUtils.getElementText(parent, name)`
30596
+ * resolves the child by name and reads its text, but we sometimes already have
30597
+ * the element reference (from a previous lookup or namespace check) and need
30598
+ * to read text from THAT element, not search again from a parent.
30599
+ *
30600
+ * @param {Element|Object} el
30601
+ * @return {String}
30602
+ */
30603
+ function _readElementText(el) {
30604
+ if (!el) {
30605
+ return '';
30606
+ }
30607
+ // Browser DOM and xmldom both expose textContent.
30608
+ if (typeof el.textContent === 'string') {
30609
+ return el.textContent;
30610
+ }
30611
+ // ltx / node-xmpp-client Element: getText() returns the concatenated
30612
+ // text of all string children.
30613
+ if (typeof el.getText === 'function') {
30614
+ return el.getText();
30615
+ }
30616
+ // Last resort: walk .children if present.
30617
+ if (el.children && el.children.length !== undefined) {
30618
+ var out = '';
30619
+ for (var i = 0; i < el.children.length; i++) {
30620
+ var c = el.children[i];
30621
+ if (typeof c === 'string') {
30622
+ out += c;
30623
+ }
30624
+ }
30625
+ return out;
30626
+ }
30627
+ return '';
30628
+ }
30629
+
30630
+ /**
30631
+ * Returns the moduleIdentifier value if and only if its xmlns attribute equals
30632
+ * urn:xmpp:notice:0. Matching only by text without namespace check is unsafe
30633
+ * (existing SystemNotifications stanzas use the same element name).
30634
+ * @param {Element} extraParams
30635
+ * @return {String|null} known notice moduleIdentifier value or null.
30636
+ */
30637
+ function _getNoticeModuleIdentifier(extraParams) {
30638
+ if (!extraParams) {
30639
+ return null;
30640
+ }
30641
+
30642
+ var moduleIdEl = chatUtils.getElement(extraParams, 'moduleIdentifier');
30643
+ if (!moduleIdEl) {
30644
+ return null;
30645
+ }
30646
+
30647
+ // Namespace check: stanza is a Notice only when xmlns equals NOTICE_NAMESPACE.
30648
+ var xmlns = chatUtils.getAttr(moduleIdEl, 'xmlns');
30649
+ if (xmlns !== noticeConsts.NOTICE_NAMESPACE) {
30650
+ return null;
30651
+ }
30652
+
30653
+ var text = (_readElementText(moduleIdEl) || '').trim();
30654
+ if (!NOTICE_KNOWN_MODULE_IDS[text]) {
30655
+ return null;
30656
+ }
30657
+
30658
+ return text;
30659
+ }
30660
+
30661
+ /**
30662
+ * Convert a CSV string of numeric ids ("10,11,13007") to Array<Number>.
30663
+ * Empty or null input → empty array. Non-numeric items are dropped silently.
30664
+ */
30665
+ function _parseNumericIdsCsv(value) {
30666
+ if (value === null || value === undefined || value === '') {
30667
+ return [];
30668
+ }
30669
+ var parts = String(value).split(',');
30670
+ var out = [];
30671
+ for (var i = 0; i < parts.length; i++) {
30672
+ var n = parseInt(parts[i], 10);
30673
+ if (!isNaN(n)) {
30674
+ out.push(n);
30675
+ }
30676
+ }
30677
+ return out;
30678
+ }
30679
+
30680
+ /**
30681
+ * Parse <reactions><reaction>{name,count,<user_ids>...}...</reaction></reactions>
30682
+ * aggregate snapshot used in NoticeUpdatedMessage text-update stanzas.
30683
+ * Reference: Android QBReactionsPropertyParser.java.
30684
+ *
30685
+ * @param {Element} extraParams
30686
+ * @return {Array<{name, count, user_ids: number[]}>|null} or null if absent.
30687
+ */
30688
+ function _parseAggregateReactions(extraParams) {
30689
+ var reactionsEl = chatUtils.getElement(extraParams, 'reactions');
30690
+ if (!reactionsEl) {
30691
+ return null;
30692
+ }
30693
+
30694
+ var out = [];
30695
+ var reactionChildren = _getChildElements(reactionsEl, 'reaction');
30696
+ for (var i = 0; i < reactionChildren.length; i++) {
30697
+ var child = reactionChildren[i];
30698
+
30699
+ try {
30700
+ var name = chatUtils.getElementText(child, 'name');
30701
+ var countText = chatUtils.getElementText(child, 'count');
30702
+ var count = parseInt(countText, 10);
30703
+ if (isNaN(count)) {
30704
+ count = 0;
30705
+ }
30706
+
30707
+ var userIds = [];
30708
+ var userIdsEl = chatUtils.getElement(child, 'user_ids');
30709
+ if (userIdsEl) {
30710
+ var uidEls = _getChildElements(userIdsEl, 'user_id');
30711
+ for (var j = 0; j < uidEls.length; j++) {
30712
+ var uid = parseInt((_readElementText(uidEls[j]) || '').trim(), 10);
30713
+ if (!isNaN(uid)) {
30714
+ userIds.push(uid);
30715
+ }
30716
+ }
30717
+ }
30718
+
30719
+ out.push({ name: name, count: count, user_ids: userIds });
30720
+ } catch (err) {
30721
+ // Malformed reaction child — skip silently per AC#9 (no exceptions).
30722
+ }
30723
+ }
30724
+
30725
+ return out;
30726
+ }
30727
+
30728
+ /**
30729
+ * Parse singular <reaction>{name,user_id,action}</reaction> incremental
30730
+ * add/remove event used in NoticeUpdatedMessage stanzas. Reference: Android
30731
+ * QBReactionPropertyParser.java.
30732
+ *
30733
+ * @param {Element} extraParams
30734
+ * @return {Object|null} singular reaction descriptor or null if absent.
30735
+ */
30736
+ function _parseSingularReaction(extraParams) {
30737
+ var reactionEl = chatUtils.getElement(extraParams, 'reaction');
30738
+ if (!reactionEl) {
30739
+ return null;
30740
+ }
30741
+
30742
+ try {
30743
+ var name = chatUtils.getElementText(reactionEl, 'name');
30744
+ var userIdText = chatUtils.getElementText(reactionEl, 'user_id');
30745
+ var action = chatUtils.getElementText(reactionEl, 'action');
30746
+
30747
+ if (!action || (action !== 'add' && action !== 'remove')) {
30748
+ return null;
30749
+ }
30750
+
30751
+ var userId = parseInt(userIdText, 10);
30752
+ if (isNaN(userId)) {
30753
+ userId = userIdText;
30754
+ }
30755
+
30756
+ return {
30757
+ name: name,
30758
+ userId: userId,
30759
+ action: action
30760
+ };
30761
+ } catch (err) {
30762
+ return null;
30763
+ }
30764
+ }
30765
+
30766
+ /**
30767
+ * Parse custom_data element. Two server formats supported:
30768
+ * 1) Nested XML: <custom_data><class_name>...</class_name>...</custom_data>
30769
+ * 2) JSON string: <custom_data>{"class_name":"...",...}</custom_data>
30770
+ * Returns plain object or undefined if custom_data is absent.
30771
+ * Reference: Android QBDialogCustomDataNoticeParser.java.
30772
+ */
30773
+ function _parseCustomData(extraParams) {
30774
+ var customDataEl = chatUtils.getElement(extraParams, 'custom_data');
30775
+ if (!customDataEl) {
30776
+ return undefined;
30777
+ }
30778
+
30779
+ var rawText = (_readElementText(customDataEl) || '').trim();
30780
+ if (rawText && rawText.charAt(0) === '{') {
30781
+ // JSON form.
30782
+ try {
30783
+ return JSON.parse(rawText);
30784
+ } catch (err) {
30785
+ // Fall through to nested-XML parsing.
30786
+ }
30787
+ }
30788
+
30789
+ // Nested XML: walk element children, build flat map of name → text.
30790
+ // Cross-env: collect all element children regardless of name, then read
30791
+ // their tag and text. _getChildElements expects a name filter, but here
30792
+ // we want every child element, so do a one-off walk.
30793
+ var out = {};
30794
+ var hasChildEl = false;
30795
+
30796
+ // Browser DOM / xmldom path.
30797
+ if (customDataEl.childNodes && customDataEl.childNodes.length !== undefined && typeof customDataEl.childNodes !== 'function') {
30798
+ for (var i = 0; i < customDataEl.childNodes.length; i++) {
30799
+ var child = customDataEl.childNodes[i];
30800
+ if (!child || child.nodeType !== 1) {
30801
+ continue;
30802
+ }
30803
+ hasChildEl = true;
30804
+ var key = child.tagName || child.nodeName || child.localName;
30805
+ out[key] = (_readElementText(child) || '').trim();
30806
+ }
30807
+ }
30808
+
30809
+ // ltx fallback: walk .children for Element-like objects.
30810
+ if (!hasChildEl && customDataEl.children && customDataEl.children.length !== undefined) {
30811
+ for (var k = 0; k < customDataEl.children.length; k++) {
30812
+ var ch = customDataEl.children[k];
30813
+ if (ch && typeof ch === 'object' && ch.name) {
30814
+ hasChildEl = true;
30815
+ out[ch.name] = (_readElementText(ch) || '').trim();
30816
+ }
30817
+ }
30818
+ }
30819
+
30820
+ if (!hasChildEl) {
30821
+ return undefined;
30822
+ }
30823
+ return out;
30824
+ }
30825
+
30826
+ /**
30827
+ * Parse a Notice headline stanza into {type, payload} ready for routing.
30828
+ * Returns null if stanza is not a Notice (no urn:xmpp:notice:0 namespace, or
30829
+ * unknown moduleIdentifier value).
30830
+ *
30831
+ * @param {Element} stanza - <message type="headline"> element from Strophe / xmpp-client.
30832
+ * @return {{type: String, payload: Object}|null}
30833
+ */
30834
+ function _parseNoticeStanza(stanza) {
30835
+ if (!stanza) {
30836
+ return null;
30837
+ }
30838
+ var extraParams = chatUtils.getElement(stanza, 'extraParams');
30839
+ if (!extraParams) {
30840
+ return null;
30841
+ }
30842
+
30843
+ var type = _getNoticeModuleIdentifier(extraParams);
30844
+ if (!type) {
30845
+ return null;
30846
+ }
30847
+
30848
+ // Common flat fields used across most notice variants.
30849
+ var dialogId = chatUtils.getElementText(extraParams, 'dialog_id');
30850
+ var messageId = chatUtils.getElementText(extraParams, 'message_id');
30851
+ var dateSentText = chatUtils.getElementText(extraParams, 'date_sent');
30852
+ var dateSent = parseInt(dateSentText, 10);
30853
+ if (isNaN(dateSent)) {
30854
+ dateSent = undefined;
30855
+ }
30856
+
30857
+ var payload;
30858
+ var IDS = noticeConsts.NOTICE_MODULE_IDENTIFIER;
30859
+
30860
+ if (type === IDS.DELETED_MESSAGE) {
30861
+ payload = {
30862
+ dialogId: dialogId,
30863
+ messageId: messageId,
30864
+ dateSent: dateSent
30865
+ };
30866
+ } else if (type === IDS.DELETED_DIALOG) {
30867
+ payload = {
30868
+ dialogId: dialogId,
30869
+ dateSent: dateSent
30870
+ };
30871
+ } else if (type === IDS.UPDATED_MESSAGE) {
30872
+ // Two variants: singular <reaction> (incremental) vs aggregate <reactions> (text update with snapshot).
30873
+ var singular = _parseSingularReaction(extraParams);
30874
+ if (singular) {
30875
+ payload = {
30876
+ kind: 'reaction',
30877
+ event: {
30878
+ dialogId: dialogId,
30879
+ messageId: messageId,
30880
+ reactionName: singular.name,
30881
+ userId: singular.userId,
30882
+ action: singular.action,
30883
+ dateSent: dateSent
30884
+ }
30885
+ };
30886
+ } else {
30887
+ // Build a partial QBChatMessage object from extraParams.
30888
+ // We read the well-known fields explicitly (no dependency on parseExtraParams,
30889
+ // which has env-specific branches and can throw on non-standard stanza shapes).
30890
+ var msg = {};
30891
+ msg._id = messageId;
30892
+ msg.chat_dialog_id = dialogId;
30893
+ if (dateSent !== undefined) {
30894
+ msg.date_sent = dateSent;
30895
+ }
30896
+ var msgText = chatUtils.getElementText(extraParams, 'message');
30897
+ if (msgText) {
30898
+ msg.message = msgText;
30899
+ }
30900
+ var senderIdText = chatUtils.getElementText(extraParams, 'sender_id');
30901
+ var senderId = parseInt(senderIdText, 10);
30902
+ if (!isNaN(senderId)) { msg.sender_id = senderId; }
30903
+ var recipientIdText = chatUtils.getElementText(extraParams, 'recipient_id');
30904
+ var recipientId = parseInt(recipientIdText, 10);
30905
+ if (!isNaN(recipientId)) { msg.recipient_id = recipientId; }
30906
+ var readIds = _parseNumericIdsCsv(chatUtils.getElementText(extraParams, 'read_ids'));
30907
+ if (readIds.length > 0) { msg.read_ids = readIds; }
30908
+ var deliveredIds = _parseNumericIdsCsv(chatUtils.getElementText(extraParams, 'delivered_ids'));
30909
+ if (deliveredIds.length > 0) { msg.delivered_ids = deliveredIds; }
30910
+ // Aggregate reactions (if any).
30911
+ var aggregate = _parseAggregateReactions(extraParams);
30912
+ if (aggregate !== null && aggregate.length > 0) {
30913
+ msg.reactions = aggregate;
30914
+ }
30915
+ payload = {
30916
+ kind: 'message',
30917
+ dialogId: dialogId,
30918
+ message: msg
30919
+ };
30920
+ }
30921
+ } else if (type === IDS.UPDATED_DIALOG) {
30922
+ // Build a partial QBChatDialog object from extraParams (full server snapshot).
30923
+ var dlg = {};
30924
+ dlg._id = dialogId;
30925
+ var name = chatUtils.getElementText(extraParams, 'name');
30926
+ if (name !== undefined && name !== null && name !== '') {
30927
+ dlg.name = name;
30928
+ }
30929
+ var photo = chatUtils.getElementText(extraParams, 'photo');
30930
+ if (photo !== undefined && photo !== null && photo !== '') {
30931
+ dlg.photo = photo;
30932
+ }
30933
+ var typeText = chatUtils.getElementText(extraParams, 'type');
30934
+ var typeNum = parseInt(typeText, 10);
30935
+ if (!isNaN(typeNum)) {
30936
+ dlg.type = typeNum;
30937
+ }
30938
+ var occupants = _parseNumericIdsCsv(chatUtils.getElementText(extraParams, 'occupants_ids'));
30939
+ if (occupants.length > 0) {
30940
+ dlg.occupants_ids = occupants;
30941
+ }
30942
+ var admins = _parseNumericIdsCsv(chatUtils.getElementText(extraParams, 'admin_ids'));
30943
+ if (admins.length > 0) {
30944
+ dlg.admin_ids = admins;
30945
+ }
30946
+ var isJoinReqText = chatUtils.getElementText(extraParams, 'is_join_required');
30947
+ if (isJoinReqText !== undefined && isJoinReqText !== null && isJoinReqText !== '') {
30948
+ var isJoinReq = parseInt(isJoinReqText, 10);
30949
+ dlg.is_join_required = isNaN(isJoinReq) ? isJoinReqText : isJoinReq;
30950
+ }
30951
+ var roomJid = chatUtils.getElementText(extraParams, 'xmpp_room_jid');
30952
+ if (roomJid !== undefined && roomJid !== null && roomJid !== '') {
30953
+ dlg.xmpp_room_jid = roomJid;
30954
+ }
30955
+ var customData = _parseCustomData(extraParams);
30956
+ if (customData !== undefined) {
30957
+ dlg.custom_data = customData;
30958
+ }
30959
+ // Last message fields.
30960
+ var lmText = chatUtils.getElementText(extraParams, 'last_message');
30961
+ if (lmText) { dlg.last_message = lmText; }
30962
+ var lmId = chatUtils.getElementText(extraParams, 'last_message_id');
30963
+ if (lmId) { dlg.last_message_id = lmId; }
30964
+ var lmDsText = chatUtils.getElementText(extraParams, 'last_message_date_sent');
30965
+ var lmDs = parseInt(lmDsText, 10);
30966
+ if (!isNaN(lmDs)) { dlg.last_message_date_sent = lmDs; }
30967
+ var lmUidText = chatUtils.getElementText(extraParams, 'last_message_user_id');
30968
+ var lmUid = parseInt(lmUidText, 10);
30969
+ if (!isNaN(lmUid)) { dlg.last_message_user_id = lmUid; }
30970
+
30971
+ payload = {
30972
+ kind: 'dialog',
30973
+ dialog: dlg
30974
+ };
30975
+ } else {
30976
+ return null;
30977
+ }
30978
+
30979
+ return { type: type, payload: payload };
30980
+ }
30981
+
30982
+ /**
30983
+ * Route a parsed Notice event to the matching listener-property on chatProxy.
30984
+ * No-op if the listener is null/undefined. Listener exceptions are caught by
30985
+ * Utils.safeCallbackCall (existing SDK convention).
30986
+ *
30987
+ * @param {ChatProxy} chatProxy
30988
+ * @param {{type: String, payload: Object}} parsed
30989
+ */
30990
+ function _routeNoticeEvent(chatProxy, parsed) {
30991
+ if (!chatProxy || !parsed) {
30992
+ return;
30993
+ }
30994
+ var IDS = noticeConsts.NOTICE_MODULE_IDENTIFIER;
30995
+ var type = parsed.type;
30996
+ var p = parsed.payload || {};
30997
+
30998
+ if (type === IDS.DELETED_MESSAGE) {
30999
+ if (typeof chatProxy.onMessageDeletedListener === 'function') {
31000
+ Utils.safeCallbackCall(chatProxy.onMessageDeletedListener, p.dialogId, p.messageId, p.dateSent);
31001
+ }
31002
+ } else if (type === IDS.UPDATED_MESSAGE) {
31003
+ if (p.kind === 'reaction') {
31004
+ if (typeof chatProxy.onMessageReactionChangedListener === 'function') {
31005
+ Utils.safeCallbackCall(chatProxy.onMessageReactionChangedListener, p.event);
31006
+ }
31007
+ } else if (p.kind === 'message') {
31008
+ if (typeof chatProxy.onMessageUpdatedListener === 'function') {
31009
+ Utils.safeCallbackCall(chatProxy.onMessageUpdatedListener, p.dialogId, p.message);
31010
+ }
31011
+ }
31012
+ } else if (type === IDS.DELETED_DIALOG) {
31013
+ if (typeof chatProxy.onDialogDeletedListener === 'function') {
31014
+ Utils.safeCallbackCall(chatProxy.onDialogDeletedListener, p.dialogId, p.dateSent);
31015
+ }
31016
+ } else if (type === IDS.UPDATED_DIALOG) {
31017
+ if (typeof chatProxy.onDialogUpdatedListener === 'function') {
31018
+ Utils.safeCallbackCall(chatProxy.onDialogUpdatedListener, p.dialog);
31019
+ }
31020
+ }
31021
+ }
31022
+
31023
+ // ============================================================================
31024
+ // End of Notice Feature parsing helpers
31025
+ // ============================================================================
31026
+
31027
+
30525
31028
 
30526
31029
  function ChatProxy(service) {
30527
31030
  var self = this;
@@ -30598,6 +31101,23 @@ function ChatProxy(service) {
30598
31101
  this._sessionHasExpired = false;
30599
31102
  this._pings = {};
30600
31103
 
31104
+ /**
31105
+ * Notice Feature local state (CROS-1055, SDK 2.24.0).
31106
+ * Reflects the current XMPP session subscription only — reset to false on disconnect.
31107
+ * Consumers must call enableNotices() again after reconnect to re-subscribe.
31108
+ */
31109
+ this._isNoticesEnabled = false;
31110
+
31111
+ /**
31112
+ * Notice listener properties (CROS-1055). All initialized to null.
31113
+ * Single-listener pattern matching existing onMessageListener / onSystemMessageListener style.
31114
+ */
31115
+ this.onMessageDeletedListener = null;
31116
+ this.onMessageUpdatedListener = null;
31117
+ this.onMessageReactionChangedListener = null;
31118
+ this.onDialogDeletedListener = null;
31119
+ this.onDialogUpdatedListener = null;
31120
+
30601
31121
  // [QC-1550] XMPP connection is considered "verified" only after the first
30602
31122
  // successful pong response. Strophe emits Status.CONNECTED at the transport
30603
31123
  // layer (TCP/WebSocket handshake completed) before XMPP-level traffic is
@@ -31179,9 +31699,23 @@ function ChatProxy(service) {
31179
31699
  delay = chatUtils.getElement(stanza, 'delay'),
31180
31700
  moduleIdentifier = chatUtils.getElementText(extraParams, 'moduleIdentifier'),
31181
31701
  bodyContent = chatUtils.getElementText(stanza, 'body'),
31182
- extraParamsParsed = chatUtils.parseExtraParams(extraParams),
31702
+ extraParamsParsed,
31183
31703
  message;
31184
31704
 
31705
+ // CROS-1055: parseExtraParams may throw on edge-case stanza shapes
31706
+ // (e.g. test fixtures using xmldom which lacks .children). Catch
31707
+ // defensively so a parsing failure doesn't kill the whole headline
31708
+ // handler — Notice routing must still run.
31709
+ try {
31710
+ extraParamsParsed = chatUtils.parseExtraParams(extraParams);
31711
+ } catch (parseErr) {
31712
+ extraParamsParsed = {};
31713
+ Utils.QBLog('[QBChat]', '[parseExtraParams] failed: ' + (parseErr && parseErr.message ? parseErr.message : parseErr));
31714
+ }
31715
+ if (!extraParamsParsed) {
31716
+ extraParamsParsed = {};
31717
+ }
31718
+
31185
31719
  if (moduleIdentifier === 'SystemNotifications' && typeof self.onSystemMessageListener === 'function') {
31186
31720
  message = {
31187
31721
  id: messageId,
@@ -31193,6 +31727,20 @@ function ChatProxy(service) {
31193
31727
  Utils.safeCallbackCall(self.onSystemMessageListener, message);
31194
31728
  } else if (self.webrtcSignalingProcessor && !delay && moduleIdentifier === 'WebRTCVideoChat') {
31195
31729
  self.webrtcSignalingProcessor._onMessage(from, extraParams, delay, userId, extraParamsParsed.extension);
31730
+ } else {
31731
+ // Notice Feature (CROS-1055, SDK 2.24.0). Sibling branch — only triggers
31732
+ // when extraParams contains <moduleIdentifier xmlns="urn:xmpp:notice:0">.
31733
+ // Non-notice headline stanzas (e.g. legacy SystemNotifications without
31734
+ // matching xmlns) fall through to the parser which returns null.
31735
+ try {
31736
+ var noticeParsed = _parseNoticeStanza(stanza);
31737
+ if (noticeParsed) {
31738
+ _routeNoticeEvent(self, noticeParsed);
31739
+ }
31740
+ } catch (err) {
31741
+ // Per AC#9: never throw from headline handler.
31742
+ Utils.QBLog('[QBChat]', '[Notice] handler error: ' + (err && err.message ? err.message : err));
31743
+ }
31196
31744
  }
31197
31745
 
31198
31746
  /**
@@ -31758,6 +32306,7 @@ ChatProxy.prototype = {
31758
32306
  self._isConnectionVerified = true;
31759
32307
  self._isReconnectListenerPending = false;
31760
32308
 
32309
+ // TODO(2.25.0): auto-enable Notice Feature here (see qbChat.js enableNotices JSDoc).
31761
32310
  self.roster.get(function (contacts) {
31762
32311
  xmppClient.send(presence);
31763
32312
 
@@ -32391,6 +32940,10 @@ ChatProxy.prototype = {
32391
32940
  this._isLogout = true;
32392
32941
  this.helpers.setUserCurrentJid('');
32393
32942
 
32943
+ // Notice Feature (CROS-1055): reset local subscription flag on disconnect.
32944
+ // Consumers must call enableNotices() again after a new connection.
32945
+ this._isNoticesEnabled = false;
32946
+
32394
32947
  if (Utils.getEnv().browser) {
32395
32948
  this.connection.flush();
32396
32949
  this.connection.disconnect('call QB.chat.disconnect');//artik should add reason = 'disconnect from SDK'
@@ -32404,6 +32957,130 @@ ChatProxy.prototype = {
32404
32957
  }
32405
32958
  },
32406
32959
 
32960
+ /**
32961
+ * Subscribe the current XMPP session to Notice Feature stanzas
32962
+ * (urn:xmpp:notice:0). After a successful IQ result the server starts
32963
+ * delivering NoticeUpdatedMessage / NoticeDeletedMessage /
32964
+ * NoticeUpdatedDialog / NoticeDeletedDialog headline stanzas.
32965
+ *
32966
+ * The local enabled flag is reset to false on chat disconnect — consumers
32967
+ * must call enableNotices() again after a reconnect (intentional divergence
32968
+ * from the Android SDK, which auto-restores the subscription).
32969
+ *
32970
+ * TODO(2.25.0): make auto-enable SDK-internal — fire on initial connect and
32971
+ * on relogin after session-expired, skip on Stream-Management reconnect.
32972
+ * Spec & three-state matrix are tracked in the internal 2.25.0 backlog
32973
+ * (auto-enable notices).
32974
+ *
32975
+ * Do not call enableNotices again before the previous callback fires —
32976
+ * concurrent enable calls are not specified.
32977
+ *
32978
+ * @memberof QB.chat
32979
+ * @param {enableNoticesCallback} callback - Called with (error, result) on IQ result.
32980
+ * @since 2.24.0
32981
+ */
32982
+ enableNotices: function (callback) {
32983
+ /**
32984
+ * Callback for QB.chat.enableNotices().
32985
+ * @callback enableNoticesCallback
32986
+ * @param {Object|null} error - Error object on failure, null on success.
32987
+ * @param {Object} [result] - IQ result element on success.
32988
+ */
32989
+ this._sendNoticeIQ('enable', callback);
32990
+ },
32991
+
32992
+ /**
32993
+ * Unsubscribe the current XMPP session from Notice Feature stanzas.
32994
+ * Sends a <disable xmlns="urn:xmpp:notice:0"/> IQ. On success the local
32995
+ * enabled flag becomes false; the server stops delivering notice stanzas.
32996
+ *
32997
+ * @memberof QB.chat
32998
+ * @param {disableNoticesCallback} callback - Called with (error, result) on IQ result.
32999
+ * @since 2.24.0
33000
+ */
33001
+ disableNotices: function (callback) {
33002
+ /**
33003
+ * Callback for QB.chat.disableNotices().
33004
+ * @callback disableNoticesCallback
33005
+ * @param {Object|null} error - Error object on failure, null on success.
33006
+ * @param {Object} [result] - IQ result element on success.
33007
+ */
33008
+ this._sendNoticeIQ('disable', callback);
33009
+ },
33010
+
33011
+ /**
33012
+ * Returns the local Notice Feature subscription flag.
33013
+ * @memberof QB.chat
33014
+ * @return {Boolean} true after a successful enableNotices(), false otherwise.
33015
+ * Reset to false on chat disconnect; not synchronized with the server.
33016
+ * @since 2.24.0
33017
+ */
33018
+ isNoticesEnabled: function () {
33019
+ return this._isNoticesEnabled === true;
33020
+ },
33021
+
33022
+ /**
33023
+ * @private
33024
+ * Internal IQ helper used by enableNotices/disableNotices. Implements the
33025
+ * dual-env IQ pattern (browser/Strophe vs Node/NativeScript stanza-builder)
33026
+ * used elsewhere in the SDK (see RosterProxy.get for the canonical reference).
33027
+ *
33028
+ * @param {String} action - 'enable' or 'disable'.
33029
+ * @param {Function} callback
33030
+ */
33031
+ _sendNoticeIQ: function (action, callback) {
33032
+ var self = this;
33033
+ var iqParams = {
33034
+ type: 'set',
33035
+ from: self.helpers.getUserCurrentJid(),
33036
+ id: chatUtils.getUniqueId('notice_' + action)
33037
+ };
33038
+ var builder = Utils.getEnv().browser ? $iq : XMPP.Stanza;
33039
+ var iq = chatUtils.createStanza(builder, iqParams, 'iq');
33040
+
33041
+ // Append <enable xmlns="urn:xmpp:notice:0"/> or <disable xmlns="..."/>
33042
+ iq.c(action, { xmlns: noticeConsts.NOTICE_NAMESPACE }).up();
33043
+
33044
+ function _onSuccess(stanza) {
33045
+ self._isNoticesEnabled = (action === 'enable');
33046
+ if (typeof callback === 'function') {
33047
+ Utils.safeCallbackCall(callback, null, stanza);
33048
+ }
33049
+ }
33050
+
33051
+ function _onError(stanza) {
33052
+ // Per AC#3/AC#4: on error keep the flag unchanged (do NOT flip to true on enable error).
33053
+ if (typeof callback === 'function') {
33054
+ var err;
33055
+ try {
33056
+ err = stanza ? chatUtils.getErrorFromXMLNode(stanza) : null;
33057
+ } catch (e) {
33058
+ err = null;
33059
+ }
33060
+ if (!err) {
33061
+ err = { type: 'cancel', message: 'Notice IQ error' };
33062
+ }
33063
+ Utils.safeCallbackCall(callback, err);
33064
+ }
33065
+ }
33066
+
33067
+ if (Utils.getEnv().browser) {
33068
+ self.connection.sendIQ(iq, _onSuccess, _onError);
33069
+ } else {
33070
+ // Node/NativeScript path: register callback in nodeStanzasCallbacks map.
33071
+ self.nodeStanzasCallbacks[iqParams.id] = function (stanza) {
33072
+ // The map handler receives the result/error stanza. Inspect type to dispatch.
33073
+ var iqType = chatUtils.getAttr(stanza, 'type');
33074
+ if (iqType === 'result') {
33075
+ _onSuccess(stanza);
33076
+ } else {
33077
+ _onError(stanza);
33078
+ }
33079
+ };
33080
+ self.Client.send(iq);
33081
+ }
33082
+ },
33083
+
32407
33084
  addListener: function (params, callback) {
32408
33085
  Utils.QBLog('[Deprecated!]', 'Avoid using it, this feature will be removed in future version.');
32409
33086
 
@@ -33710,7 +34387,7 @@ Helpers.prototype = {
33710
34387
  * */
33711
34388
  module.exports = ChatProxy;
33712
34389
 
33713
- },{"../../plugins/streamManagement":150,"../../qbConfig":151,"../../qbStrophe":154,"../../qbUtils":155,"./qbChatHelpers":133,"nativescript-xmpp-client":undefined,"node-xmpp-client":54}],133:[function(require,module,exports){
34390
+ },{"../../plugins/streamManagement":151,"../../qbConfig":152,"../../qbStrophe":155,"../../qbUtils":156,"./qbChatHelpers":133,"./qbNoticeConsts":136,"nativescript-xmpp-client":undefined,"node-xmpp-client":54}],133:[function(require,module,exports){
33714
34391
  'use strict';
33715
34392
 
33716
34393
  var utils = require('../../qbUtils');
@@ -34039,7 +34716,7 @@ var qbChatHelpers = {
34039
34716
 
34040
34717
  module.exports = qbChatHelpers;
34041
34718
 
34042
- },{"../../qbConfig":151,"../../qbUtils":155}],134:[function(require,module,exports){
34719
+ },{"../../qbConfig":152,"../../qbUtils":156}],134:[function(require,module,exports){
34043
34720
  'use strict';
34044
34721
 
34045
34722
  var config = require('../../qbConfig'),
@@ -34081,9 +34758,11 @@ DialogProxy.prototype = {
34081
34758
  },
34082
34759
 
34083
34760
  /**
34084
- * Create new dialog({@link https://docs.quickblox.com/docs/js-chat-dialogs#create-dialog read more}).
34761
+ * Create new dialog({@link https://docs.quickblox.com/reference/create-dialog read more}).
34085
34762
  * @memberof QB.chat.dialog
34086
34763
  * @param {Object} params - Object of parameters.
34764
+ * @param {Number[]|String} [params.admin_ids] - IDs of dialog admins for public/group dialogs.
34765
+ * Ignored by the backend for private dialogs.
34087
34766
  * @param {createDialogCallback} callback - The callback function.
34088
34767
  * */
34089
34768
  create: function(params, callback) {
@@ -34098,6 +34777,10 @@ DialogProxy.prototype = {
34098
34777
  params.occupants_ids = params.occupants_ids.join(', ');
34099
34778
  }
34100
34779
 
34780
+ if (params && params.admin_ids && Utils.isArray(params.admin_ids)) {
34781
+ params.admin_ids = params.admin_ids.join(', ');
34782
+ }
34783
+
34101
34784
  if (params && params.is_join_required !== undefined && params.is_join_required !== null) {
34102
34785
  if (params.is_join_required !== 0 && params.is_join_required !== 1) {
34103
34786
  Utils.QBLog('[QBChat]', 'Warning: is_join_required must be 0 or 1, got: ' +
@@ -34114,10 +34797,13 @@ DialogProxy.prototype = {
34114
34797
  },
34115
34798
 
34116
34799
  /**
34117
- * Update group dialog({@link https://docs.quickblox.com/docs/js-chat-dialogs#update-dialog read more}).
34800
+ * Update group dialog({@link https://docs.quickblox.com/reference/update-dialog read more}).
34118
34801
  * @memberof QB.chat.dialog
34119
34802
  * @param {String} id - The dialog ID.
34120
34803
  * @param {Object} params - Object of parameters.
34804
+ * @param {Number[]|String} [params.admin_ids] - Full replacement list of dialog admins.
34805
+ * @param {Object} [params.push_all] - Incremental fields to append, including admin_ids.
34806
+ * @param {Object} [params.pull_all] - Incremental fields to remove, including admin_ids.
34121
34807
  * @param {updateDialogCallback} callback - The callback function.
34122
34808
  * */
34123
34809
  update: function(id, params, callback) {
@@ -34174,7 +34860,7 @@ DialogProxy.prototype = {
34174
34860
 
34175
34861
  module.exports = DialogProxy;
34176
34862
 
34177
- },{"../../qbConfig":151,"../../qbUtils":155}],135:[function(require,module,exports){
34863
+ },{"../../qbConfig":152,"../../qbUtils":156}],135:[function(require,module,exports){
34178
34864
  'use strict';
34179
34865
 
34180
34866
  var config = require('../../qbConfig'),
@@ -34194,6 +34880,9 @@ MessageProxy.prototype = {
34194
34880
  * Get a chat history({@link https://docs.quickblox.com/docs/js-chat-messaging#retrieve-chat-history read more}).
34195
34881
  * @memberof QB.chat.message
34196
34882
  * @param {Object} params - Object of parameters.
34883
+ * @param {Number} [params.include_reactions] - Include message reactions in the response.
34884
+ * Allowed values: 0 (default, no reactions data) or 1 (include reactions[] per message).
34885
+ * Reactions array shape: [{ name, count, user_ids: number[] }].
34197
34886
  * @param {listMessageCallback} callback - The callback function.
34198
34887
  * */
34199
34888
  list: function(params, callback) {
@@ -34291,6 +34980,129 @@ MessageProxy.prototype = {
34291
34980
  }
34292
34981
  },
34293
34982
 
34983
+ /**
34984
+ * Get a chat message by ID
34985
+ * ({@link https://docs.quickblox.com/reference/get-message-by-id read more}).
34986
+ * @memberof QB.chat.message
34987
+ * @param {String} id - The message id.
34988
+ * @param {Object} [params] - Optional query parameters.
34989
+ * @param {Number} [params.include_reactions] - Include message reactions in the response (0 or 1).
34990
+ * @param {getByIdMessageCallback} callback - The callback function.
34991
+ * @since 2.24.0
34992
+ * */
34993
+ getById: function(id, params_or_callback, callback) {
34994
+ /**
34995
+ * Callback for QB.chat.message.getById().
34996
+ * @param {Object} error - The error object.
34997
+ * @param {Object} message - The message object.
34998
+ * @callback getByIdMessageCallback
34999
+ * */
35000
+
35001
+ var ajaxParams = {
35002
+ url: Utils.getUrl(MESSAGES_API_URL, id)
35003
+ };
35004
+
35005
+ if (arguments.length === 2) {
35006
+ this.service.ajax(ajaxParams, params_or_callback);
35007
+ } else if (arguments.length === 3) {
35008
+ ajaxParams.data = params_or_callback;
35009
+
35010
+ this.service.ajax(ajaxParams, callback);
35011
+ }
35012
+ },
35013
+
35014
+ /**
35015
+ * Add reaction to a message.
35016
+ * @memberof QB.chat.message
35017
+ * @param {String} id - The message id.
35018
+ * @param {String} name - The reaction name.
35019
+ * @param {addReactionCallback} callback - The callback function.
35020
+ *
35021
+ * Server contract:
35022
+ * POST /chat/Message/{id}/reactions
35023
+ * Success: 201 Created with empty body.
35024
+ * Errors: 400 (invalid id/name or reaction limits), 404 (message not found), 422 (public dialog).
35025
+ *
35026
+ * Idempotency note: Re-adding the same reaction by the same user returns 201 without creating a duplicate reaction.
35027
+ * */
35028
+ addReaction: function(id, name, callback) {
35029
+ /**
35030
+ * Callback for QB.chat.message.addReaction().
35031
+ * @param {Object} error - The error object.
35032
+ * @param {Object|undefined} reaction - Empty response body on success.
35033
+ * @callback addReactionCallback
35034
+ * */
35035
+
35036
+ // Server returns 201 with empty body. Use dataType:'text' so qbProxy does
35037
+ // not try to JSON.parse the empty response (which throws in node-fetch).
35038
+ this.service.ajax({
35039
+ url: Utils.getUrl(MESSAGES_API_URL + '/' + id + '/reactions'),
35040
+ type: 'POST',
35041
+ contentType: 'application/json; charset=utf-8',
35042
+ isNeedStringify: true,
35043
+ dataType: 'text',
35044
+ data: {
35045
+ name: name
35046
+ }
35047
+ }, callback);
35048
+ },
35049
+
35050
+ /**
35051
+ * Remove reaction from a message.
35052
+ * @memberof QB.chat.message
35053
+ * @param {String} id - The message id.
35054
+ * @param {String} name - The reaction name.
35055
+ * @param {removeReactionCallback} callback - The callback function.
35056
+ *
35057
+ * Server contract:
35058
+ * DELETE /chat/Message/{id}/reactions
35059
+ * Success: 200 OK with empty body.
35060
+ * Errors: 400 (invalid id/name), 404 (message not found or reaction not found).
35061
+ * */
35062
+ removeReaction: function(id, name, callback) {
35063
+ /**
35064
+ * Callback for QB.chat.message.removeReaction().
35065
+ * @param {Object} error - The error object.
35066
+ * @param {String} response - Empty body.
35067
+ * @callback removeReactionCallback
35068
+ * */
35069
+
35070
+ this.service.ajax({
35071
+ url: Utils.getUrl(MESSAGES_API_URL + '/' + id + '/reactions'),
35072
+ type: 'DELETE',
35073
+ contentType: 'application/json; charset=utf-8',
35074
+ isNeedStringify: true,
35075
+ dataType: 'text',
35076
+ data: {
35077
+ name: name
35078
+ }
35079
+ }, callback);
35080
+ },
35081
+
35082
+ /**
35083
+ * Get reactions list for a message.
35084
+ * @memberof QB.chat.message
35085
+ * @param {String} id - The message id.
35086
+ * @param {listReactionsCallback} callback - The callback function.
35087
+ *
35088
+ * Server contract:
35089
+ * GET /chat/Message/{id}/reactions
35090
+ * Success: 200 OK, body { total_entries: Number, items: Array<{ name, count, user_ids[] }> }.
35091
+ * Errors: 400 (invalid id), 404 (message not found).
35092
+ * */
35093
+ listReactions: function(id, callback) {
35094
+ /**
35095
+ * Callback for QB.chat.message.listReactions().
35096
+ * @param {Object} error - The error object.
35097
+ * @param {Object} reactions - The reactions aggregate object.
35098
+ * @callback listReactionsCallback
35099
+ * */
35100
+
35101
+ this.service.ajax({
35102
+ url: Utils.getUrl(MESSAGES_API_URL + '/' + id + '/reactions')
35103
+ }, callback);
35104
+ },
35105
+
34294
35106
  /**
34295
35107
  * Get unread messages counter for one or group of dialogs({@link https://docs.quickblox.com/docs/js-chat-dialogs#get-number-of-unread-messages read more}).
34296
35108
  * @memberof QB.chat.message
@@ -34318,7 +35130,41 @@ MessageProxy.prototype = {
34318
35130
 
34319
35131
  module.exports = MessageProxy;
34320
35132
 
34321
- },{"../../qbConfig":151,"../../qbUtils":155}],136:[function(require,module,exports){
35133
+ },{"../../qbConfig":152,"../../qbUtils":156}],136:[function(require,module,exports){
35134
+ 'use strict';
35135
+
35136
+ /**
35137
+ * Shared constants for the Notice Feature (XMPP `urn:xmpp:notice:0`).
35138
+ *
35139
+ * Foundation module for SDK 2.24.0 — imported by Notice / Reaction / Admin Role
35140
+ * runtime modules in their respective feature branches. No runtime behavior here.
35141
+ *
35142
+ * Mirror of Android `com.quickblox.chat.notice.QBNoticeConsts`.
35143
+ */
35144
+
35145
+ /**
35146
+ * XMPP namespace for Notice IQ stanzas (`<enable>`, `<disable>`) and for the
35147
+ * `<moduleIdentifier>` element on inbound notice messages.
35148
+ */
35149
+ var NOTICE_NAMESPACE = 'urn:xmpp:notice:0';
35150
+
35151
+ /**
35152
+ * Discriminator strings carried in the `<moduleIdentifier>` element of
35153
+ * inbound notice stanzas. Used for routing in the headline-message handler.
35154
+ */
35155
+ var NOTICE_MODULE_IDENTIFIER = {
35156
+ UPDATED_MESSAGE: 'NoticeUpdatedMessage',
35157
+ DELETED_MESSAGE: 'NoticeDeletedMessage',
35158
+ UPDATED_DIALOG: 'NoticeUpdatedDialog',
35159
+ DELETED_DIALOG: 'NoticeDeletedDialog'
35160
+ };
35161
+
35162
+ module.exports = {
35163
+ NOTICE_NAMESPACE: NOTICE_NAMESPACE,
35164
+ NOTICE_MODULE_IDENTIFIER: NOTICE_MODULE_IDENTIFIER
35165
+ };
35166
+
35167
+ },{}],137:[function(require,module,exports){
34322
35168
  'use strict';
34323
35169
 
34324
35170
  var Utils = require('../qbUtils');
@@ -34672,7 +35518,7 @@ AIProxy.prototype = {
34672
35518
 
34673
35519
  module.exports = AIProxy;
34674
35520
 
34675
- },{"../qbUtils":155}],137:[function(require,module,exports){
35521
+ },{"../qbUtils":156}],138:[function(require,module,exports){
34676
35522
  'use strict';
34677
35523
 
34678
35524
  var Utils = require('../qbUtils');
@@ -34897,7 +35743,7 @@ function isFunction(func) {
34897
35743
  return !!(func && func.constructor && func.call && func.apply);
34898
35744
  }
34899
35745
 
34900
- },{"../qbConfig":151,"../qbUtils":155}],138:[function(require,module,exports){
35746
+ },{"../qbConfig":152,"../qbUtils":156}],139:[function(require,module,exports){
34901
35747
  'use strict';
34902
35748
 
34903
35749
  var config = require('../qbConfig'),
@@ -35048,7 +35894,7 @@ function signMessage(message, secret) {
35048
35894
  return cryptoSessionMsg;
35049
35895
  }
35050
35896
 
35051
- },{"../qbConfig":151,"../qbUtils":155,"crypto-js/hmac-sha1":24,"crypto-js/hmac-sha256":25}],139:[function(require,module,exports){
35897
+ },{"../qbConfig":152,"../qbUtils":156,"crypto-js/hmac-sha1":24,"crypto-js/hmac-sha256":25}],140:[function(require,module,exports){
35052
35898
  'use strict';
35053
35899
 
35054
35900
  /*
@@ -35451,7 +36297,7 @@ parseUri.options = {
35451
36297
  }
35452
36298
  };
35453
36299
 
35454
- },{"../qbConfig":151,"../qbUtils":155}],140:[function(require,module,exports){
36300
+ },{"../qbConfig":152,"../qbUtils":156}],141:[function(require,module,exports){
35455
36301
  'use strict';
35456
36302
 
35457
36303
  var config = require('../qbConfig');
@@ -35833,7 +36679,7 @@ DataProxy.prototype = {
35833
36679
 
35834
36680
  module.exports = DataProxy;
35835
36681
 
35836
- },{"../qbConfig":151,"../qbUtils":155}],141:[function(require,module,exports){
36682
+ },{"../qbConfig":152,"../qbUtils":156}],142:[function(require,module,exports){
35837
36683
  (function (Buffer){(function (){
35838
36684
  'use strict';
35839
36685
 
@@ -36072,7 +36918,7 @@ EventsProxy.prototype = {
36072
36918
  module.exports = PushNotificationsProxy;
36073
36919
 
36074
36920
  }).call(this)}).call(this,require("buffer").Buffer)
36075
- },{"../qbConfig":151,"../qbUtils":155,"buffer":21}],142:[function(require,module,exports){
36921
+ },{"../qbConfig":152,"../qbUtils":156,"buffer":21}],143:[function(require,module,exports){
36076
36922
  'use strict';
36077
36923
 
36078
36924
  /*
@@ -36385,7 +37231,7 @@ function generateOrder(obj) {
36385
37231
  return [obj.sort, type, obj.field].join(' ');
36386
37232
  }
36387
37233
 
36388
- },{"../qbConfig":151,"../qbUtils":155}],143:[function(require,module,exports){
37234
+ },{"../qbConfig":152,"../qbUtils":156}],144:[function(require,module,exports){
36389
37235
  'use strict';
36390
37236
 
36391
37237
  /**
@@ -37225,7 +38071,7 @@ qbRTCPeerConnection._applyStatReport = _applyStatReport;
37225
38071
 
37226
38072
  module.exports = qbRTCPeerConnection;
37227
38073
 
37228
- },{"../../qbConfig":151,"./qbWebRTCHelpers":145}],144:[function(require,module,exports){
38074
+ },{"../../qbConfig":152,"./qbWebRTCHelpers":146}],145:[function(require,module,exports){
37229
38075
  'use strict';
37230
38076
 
37231
38077
  /**
@@ -37636,7 +38482,7 @@ function getOpponentsIdNASessions(sessions) {
37636
38482
  return opponents;
37637
38483
  }
37638
38484
 
37639
- },{"../../qbConfig":151,"../../qbUtils":155,"./qbRTCPeerConnection":143,"./qbWebRTCHelpers":145,"./qbWebRTCSession":146,"./qbWebRTCSignalingConstants":147,"./qbWebRTCSignalingProcessor":148,"./qbWebRTCSignalingProvider":149}],145:[function(require,module,exports){
38485
+ },{"../../qbConfig":152,"../../qbUtils":156,"./qbRTCPeerConnection":144,"./qbWebRTCHelpers":146,"./qbWebRTCSession":147,"./qbWebRTCSignalingConstants":148,"./qbWebRTCSignalingProcessor":149,"./qbWebRTCSignalingProvider":150}],146:[function(require,module,exports){
37640
38486
  'use strict';
37641
38487
 
37642
38488
  /**
@@ -37782,7 +38628,7 @@ var WebRTCHelpers = {
37782
38628
 
37783
38629
  module.exports = WebRTCHelpers;
37784
38630
 
37785
- },{"../../qbConfig":151}],146:[function(require,module,exports){
38631
+ },{"../../qbConfig":152}],147:[function(require,module,exports){
37786
38632
  'use strict';
37787
38633
 
37788
38634
  /**
@@ -39145,7 +39991,7 @@ function _prepareExtension(extension) {
39145
39991
 
39146
39992
  module.exports = WebRTCSession;
39147
39993
 
39148
- },{"../../qbConfig":151,"../../qbUtils":155,"./qbRTCPeerConnection":143,"./qbWebRTCHelpers":145,"./qbWebRTCSignalingConstants":147}],147:[function(require,module,exports){
39994
+ },{"../../qbConfig":152,"../../qbUtils":156,"./qbRTCPeerConnection":144,"./qbWebRTCHelpers":146,"./qbWebRTCSignalingConstants":148}],148:[function(require,module,exports){
39149
39995
  'use strict';
39150
39996
 
39151
39997
  /**
@@ -39168,7 +40014,7 @@ WebRTCSignalingConstants.SignalingType = {
39168
40014
 
39169
40015
  module.exports = WebRTCSignalingConstants;
39170
40016
 
39171
- },{}],148:[function(require,module,exports){
40017
+ },{}],149:[function(require,module,exports){
39172
40018
  'use strict';
39173
40019
 
39174
40020
  /**
@@ -39345,7 +40191,7 @@ function WebRTCSignalingProcessor(service, delegate) {
39345
40191
 
39346
40192
  module.exports = WebRTCSignalingProcessor;
39347
40193
 
39348
- },{"./qbWebRTCSignalingConstants":147,"strophe.js":104,"strophe.js/dist/strophe.umd.js":104}],149:[function(require,module,exports){
40194
+ },{"./qbWebRTCSignalingConstants":148,"strophe.js":104,"strophe.js/dist/strophe.umd.js":104}],150:[function(require,module,exports){
39349
40195
  'use strict';
39350
40196
 
39351
40197
  /** JSHint inline rules */
@@ -39471,7 +40317,7 @@ WebRTCSignalingProvider.prototype._JStoXML = function (title, obj, msg) {
39471
40317
 
39472
40318
  module.exports = WebRTCSignalingProvider;
39473
40319
 
39474
- },{"../../qbConfig":151,"../../qbUtils":155,"./qbWebRTCHelpers":145,"./qbWebRTCSignalingConstants":147,"strophe.js":104,"strophe.js/dist/strophe.umd.js":104}],150:[function(require,module,exports){
40320
+ },{"../../qbConfig":152,"../../qbUtils":156,"./qbWebRTCHelpers":146,"./qbWebRTCSignalingConstants":148,"strophe.js":104,"strophe.js/dist/strophe.umd.js":104}],151:[function(require,module,exports){
39475
40321
  'use strict';
39476
40322
 
39477
40323
  /**
@@ -39708,7 +40554,7 @@ StreamManagement.prototype._increaseReceivedStanzasCounter = function(){
39708
40554
 
39709
40555
  module.exports = StreamManagement;
39710
40556
 
39711
- },{"../modules/chat/qbChatHelpers":133,"../qbUtils":155}],151:[function(require,module,exports){
40557
+ },{"../modules/chat/qbChatHelpers":133,"../qbUtils":156}],152:[function(require,module,exports){
39712
40558
  'use strict';
39713
40559
 
39714
40560
  /*
@@ -39723,8 +40569,8 @@ module.exports = StreamManagement;
39723
40569
  */
39724
40570
 
39725
40571
  var config = {
39726
- version: '2.23.1',
39727
- buildNumber: '1179',
40572
+ version: '2.24.0',
40573
+ buildNumber: '1180',
39728
40574
  creds: {
39729
40575
  'appId': 0,
39730
40576
  'authKey': '',
@@ -39865,7 +40711,7 @@ config.updateSessionExpirationDate = function (tokenExpirationDate, headerHasTok
39865
40711
 
39866
40712
  module.exports = config;
39867
40713
 
39868
- },{}],152:[function(require,module,exports){
40714
+ },{}],153:[function(require,module,exports){
39869
40715
  'use strict';
39870
40716
 
39871
40717
  /*
@@ -40282,7 +41128,7 @@ QB.QuickBlox = QuickBlox;
40282
41128
 
40283
41129
  module.exports = QB;
40284
41130
 
40285
- },{"./modules/chat/qbChat":132,"./modules/chat/qbDialog":134,"./modules/chat/qbMessage":135,"./modules/qbAI":136,"./modules/qbAddressBook":137,"./modules/qbAuth":138,"./modules/qbContent":139,"./modules/qbData":140,"./modules/qbPushNotifications":141,"./modules/qbUsers":142,"./modules/webrtc/qbWebRTCClient":144,"./qbConfig":151,"./qbProxy":153,"./qbUtils":155,"webrtc-adapter":117}],153:[function(require,module,exports){
41131
+ },{"./modules/chat/qbChat":132,"./modules/chat/qbDialog":134,"./modules/chat/qbMessage":135,"./modules/qbAI":137,"./modules/qbAddressBook":138,"./modules/qbAuth":139,"./modules/qbContent":140,"./modules/qbData":141,"./modules/qbPushNotifications":142,"./modules/qbUsers":143,"./modules/webrtc/qbWebRTCClient":145,"./qbConfig":152,"./qbProxy":154,"./qbUtils":156,"webrtc-adapter":117}],154:[function(require,module,exports){
40286
41132
  'use strict';
40287
41133
 
40288
41134
  var config = require('./qbConfig');
@@ -40633,7 +41479,7 @@ ServiceProxy.prototype = {
40633
41479
 
40634
41480
  module.exports = ServiceProxy;
40635
41481
 
40636
- },{"./qbConfig":151,"./qbUtils":155,"form-data":32,"node-fetch":53}],154:[function(require,module,exports){
41482
+ },{"./qbConfig":152,"./qbUtils":156,"form-data":32,"node-fetch":53}],155:[function(require,module,exports){
40637
41483
  'use strict';
40638
41484
  /** JSHint inline rules */
40639
41485
  /* globals Strophe */
@@ -40741,7 +41587,7 @@ function Connection(onLogListenerCallback) {
40741
41587
 
40742
41588
  module.exports = Connection;
40743
41589
 
40744
- },{"./qbConfig":151,"./qbUtils":155,"strophe.js":104,"strophe.js/dist/strophe.umd.js":104}],155:[function(require,module,exports){
41590
+ },{"./qbConfig":152,"./qbUtils":156,"strophe.js":104,"strophe.js/dist/strophe.umd.js":104}],156:[function(require,module,exports){
40745
41591
  (function (global){(function (){
40746
41592
  /* eslint no-console: 2 */
40747
41593
 
@@ -41145,5 +41991,5 @@ var Utils = {
41145
41991
  module.exports = Utils;
41146
41992
 
41147
41993
  }).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
41148
- },{"./qbConfig":151,"fs":20,"os":81}]},{},[152])(152)
41994
+ },{"./qbConfig":152,"fs":20,"os":81}]},{},[153])(153)
41149
41995
  });