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/package.json +1 -1
- package/quickblox.d.ts +216 -2
- package/quickblox.js +876 -30
- package/quickblox.min.js +1 -1
- package/src/modules/chat/qbChat.js +679 -2
- package/src/modules/chat/qbDialog.js +11 -2
- package/src/modules/chat/qbMessage.js +126 -0
- package/src/modules/chat/qbNoticeConsts.js +32 -0
- package/src/qbConfig.js +2 -2
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
|
|
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":
|
|
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":
|
|
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/
|
|
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/
|
|
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":
|
|
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":
|
|
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":
|
|
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":
|
|
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":
|
|
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":
|
|
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":
|
|
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":
|
|
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":
|
|
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":
|
|
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":
|
|
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":
|
|
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":
|
|
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
|
-
},{}],
|
|
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":
|
|
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":
|
|
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":
|
|
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.
|
|
39727
|
-
buildNumber: '
|
|
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
|
-
},{}],
|
|
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":
|
|
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":
|
|
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":
|
|
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":
|
|
41994
|
+
},{"./qbConfig":152,"fs":20,"os":81}]},{},[153])(153)
|
|
41149
41995
|
});
|