Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
ae502a53c2
@ -827,7 +827,7 @@
|
||||
test_utils.openChatBoxFor(_converse, sender_jid);
|
||||
|
||||
var chatboxview = _converse.chatboxviews.get(sender_jid);
|
||||
spyOn(chatboxview, 'scrollDown').and.callThrough();
|
||||
spyOn(chatboxview, 'onScrolledDown').and.callThrough();
|
||||
|
||||
// Create enough messages so that there's a scrollbar.
|
||||
var message = 'This message is received while the chat area is scrolled up';
|
||||
@ -841,13 +841,13 @@
|
||||
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
|
||||
}
|
||||
return test_utils.waitUntil(function () {
|
||||
return chatboxview.$content.scrollTop();
|
||||
return chatboxview.content.scrollTop;
|
||||
}, 1000).then(function () {
|
||||
return test_utils.waitUntil(function () {
|
||||
return !chatboxview.model.get('auto_scrolled');
|
||||
}, 500);
|
||||
}).then(function () {
|
||||
chatboxview.$content.scrollTop(0);
|
||||
chatboxview.content.scrollTop = 0;
|
||||
return test_utils.waitUntil(function () {
|
||||
return chatboxview.model.get('scrolled');
|
||||
}, 900);
|
||||
@ -869,10 +869,10 @@
|
||||
}, 500);
|
||||
}).then(function () {
|
||||
expect(chatboxview.model.get('scrolled')).toBe(true);
|
||||
expect(chatboxview.$content.scrollTop()).toBe(0);
|
||||
expect(chatboxview.content.scrollTop).toBe(0);
|
||||
expect(chatboxview.$('.new-msgs-indicator').is(':visible')).toBeTruthy();
|
||||
// Scroll down again
|
||||
chatboxview.$content.scrollTop(chatboxview.$content[0].scrollHeight);
|
||||
chatboxview.content.scrollTop = chatboxview.content.scrollHeight;
|
||||
return test_utils.waitUntil(function () {
|
||||
return !chatboxview.$('.new-msgs-indicator').is(':visible');
|
||||
}, 700);
|
||||
|
@ -1356,7 +1356,7 @@
|
||||
}
|
||||
// Give enough time for `markScrolled` to have been called
|
||||
setTimeout(function () {
|
||||
view.$content.scrollTop(0);
|
||||
view.content.scrollTop = 0;
|
||||
view.handleMUCMessage(
|
||||
$msg({
|
||||
from: 'lounge@localhost/someone',
|
||||
@ -1369,7 +1369,7 @@
|
||||
var $chat_content = view.$el.find('.chat-content');
|
||||
var msg_txt = $chat_content.find('.chat-message:last').find('.chat-msg-content').text();
|
||||
expect(msg_txt).toEqual(message);
|
||||
expect(view.$content.scrollTop()).toBe(0);
|
||||
expect(view.content.scrollTop).toBe(0);
|
||||
done();
|
||||
}, 500);
|
||||
});
|
||||
|
@ -8,7 +8,6 @@
|
||||
|
||||
(function (root, factory) {
|
||||
define([
|
||||
"jquery.noconflict",
|
||||
"converse-core",
|
||||
"converse-chatboxes",
|
||||
"emojione",
|
||||
@ -25,7 +24,6 @@
|
||||
"tpl!toolbar"
|
||||
], factory);
|
||||
}(this, function (
|
||||
$,
|
||||
converse,
|
||||
dummy,
|
||||
emojione,
|
||||
@ -265,6 +263,7 @@
|
||||
},
|
||||
|
||||
initialize () {
|
||||
this.scrollDown = _.debounce(this._scrollDown, 250);
|
||||
this.markScrolled = _.debounce(this._markScrolled, 100);
|
||||
this.createEmojiPicker();
|
||||
this.model.messages.on('add', this.onMessageAdded, this);
|
||||
@ -295,7 +294,6 @@
|
||||
}
|
||||
));
|
||||
this.content = this.el.querySelector('.chat-content');
|
||||
this.$content = $(this.content);
|
||||
return this;
|
||||
},
|
||||
|
||||
@ -348,7 +346,7 @@
|
||||
},
|
||||
|
||||
clearStatusNotification () {
|
||||
u.removeElement(this.content.querySelector('div.chat-event'));
|
||||
u.removeElement(this.content.querySelector('.chat-event'));
|
||||
},
|
||||
|
||||
showStatusNotification (message, keep_old, permanent) {
|
||||
@ -409,9 +407,9 @@
|
||||
* Parameters:
|
||||
* (Object) attrs: An object containing the message attributes.
|
||||
*/
|
||||
_.flow(($el) => {
|
||||
insert_method($el[0]);
|
||||
return $el;
|
||||
_.flow((el) => {
|
||||
insert_method(el);
|
||||
return el;
|
||||
},
|
||||
this.scrollDown.bind(this)
|
||||
)(this.renderMessage(attrs));
|
||||
@ -564,7 +562,7 @@
|
||||
template = tpl_message;
|
||||
username = attrs.sender === 'me' && __('me') || fullname;
|
||||
}
|
||||
$(this.content).find('div.chat-event').remove();
|
||||
this.clearStatusNotification();
|
||||
|
||||
if (text.length > 8000) {
|
||||
text = text.substring(0, 10) + '...';
|
||||
@ -575,7 +573,7 @@
|
||||
true, true);
|
||||
}
|
||||
const msg_time = moment(attrs.time) || moment;
|
||||
const $msg = $(template(
|
||||
const msg = u.stringToElement(template(
|
||||
_.extend(this.getExtraMessageTemplateAttributes(attrs), {
|
||||
'msgid': attrs.msgid,
|
||||
'sender': attrs.sender,
|
||||
@ -585,12 +583,12 @@
|
||||
'extra_classes': this.getExtraMessageClasses(attrs)
|
||||
})
|
||||
));
|
||||
const msg_content = $msg[0].querySelector('.chat-msg-content');
|
||||
const msg_content = msg.querySelector('.chat-msg-content');
|
||||
msg_content.innerHTML = u.addEmoji(
|
||||
_converse, emojione, u.addHyperlinks(xss.filterXSS(text, {'whiteList': {}}))
|
||||
);
|
||||
u.renderImageURLs(msg_content);
|
||||
return $msg;
|
||||
return msg;
|
||||
},
|
||||
|
||||
showHelpMessages (msgs, type, spinner) {
|
||||
@ -604,7 +602,7 @@
|
||||
);
|
||||
});
|
||||
if (spinner === true) {
|
||||
$(this.content).append(tpl_spinner);
|
||||
this.addSpinner();
|
||||
} else if (spinner === false) {
|
||||
this.clearSpinner();
|
||||
}
|
||||
@ -629,14 +627,14 @@
|
||||
this.showStatusNotification(message.get('fullname')+' '+__('has stopped typing'));
|
||||
}
|
||||
} else if (_.includes([_converse.INACTIVE, _converse.ACTIVE], message.get('chat_state'))) {
|
||||
$(this.content).find('div.chat-event').remove();
|
||||
this.clearStatusNotification();
|
||||
} else if (message.get('chat_state') === _converse.GONE) {
|
||||
this.showStatusNotification(message.get('fullname')+' '+__('has gone away'));
|
||||
}
|
||||
},
|
||||
|
||||
shouldShowOnTextMessage () {
|
||||
return !this.$el.is(':visible');
|
||||
return !u.isVisible(this.el);
|
||||
},
|
||||
|
||||
handleTextMessage (message) {
|
||||
@ -854,12 +852,13 @@
|
||||
},
|
||||
|
||||
insertIntoTextArea (value) {
|
||||
const $textbox = this.$el.find('textarea.chat-textarea');
|
||||
let existing = $textbox.val();
|
||||
const textbox_el = this.el.querySelector('.chat-textarea');
|
||||
let existing = textbox_el.value;
|
||||
if (existing && (existing[existing.length-1] !== ' ')) {
|
||||
existing = existing + ' ';
|
||||
}
|
||||
$textbox.focus().val(existing+value+' ');
|
||||
textbox_el.value = existing+value+' ';
|
||||
textbox_el.focus()
|
||||
},
|
||||
|
||||
insertEmoji (ev) {
|
||||
@ -900,7 +899,7 @@
|
||||
const chat_status = item.get('chat_status');
|
||||
let fullname = item.get('fullname');
|
||||
fullname = _.isEmpty(fullname)? item.get('jid'): fullname;
|
||||
if (this.$el.is(':visible')) {
|
||||
if (u.isVisible(this.el)) {
|
||||
if (chat_status === 'offline') {
|
||||
this.showStatusNotification(fullname+' '+__('has gone offline'));
|
||||
} else if (chat_status === 'away') {
|
||||
@ -908,7 +907,7 @@
|
||||
} else if ((chat_status === 'dnd')) {
|
||||
this.showStatusNotification(fullname+' '+__('is busy'));
|
||||
} else if (chat_status === 'online') {
|
||||
this.$el.find('div.chat-event').remove();
|
||||
this.clearStatusNotification();
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -1043,8 +1042,8 @@
|
||||
}
|
||||
let scrolled = true;
|
||||
const is_at_bottom =
|
||||
($(this.content).scrollTop() + $(this.content).innerHeight()) >=
|
||||
$(this.content)[0].scrollHeight-10;
|
||||
(this.content.scrollTop + this.content.clientHeight) >=
|
||||
this.content.scrollHeight - 62; // sigh...
|
||||
|
||||
if (is_at_bottom) {
|
||||
scrolled = false;
|
||||
@ -1070,18 +1069,6 @@
|
||||
}
|
||||
},
|
||||
|
||||
scrollDown () {
|
||||
if (_.isUndefined(this.debouncedScrollDown)) {
|
||||
/* We wrap the method in a debouncer and set it on the
|
||||
* instance, so that we have it debounced per instance.
|
||||
* Debouncing it on the class-level is too broad.
|
||||
*/
|
||||
this.debouncedScrollDown = _.debounce(this._scrollDown, 250);
|
||||
}
|
||||
this.debouncedScrollDown.apply(this, arguments);
|
||||
return this;
|
||||
},
|
||||
|
||||
onScrolledDown() {
|
||||
this.hideNewMessagesIndicator();
|
||||
if (_converse.windowState !== 'hidden') {
|
||||
|
@ -82,6 +82,7 @@
|
||||
},
|
||||
|
||||
initialize () {
|
||||
this.scrollDown = _.debounce(this._scrollDown, 250);
|
||||
this.markScrolled = _.debounce(this._markScrolled, 100);
|
||||
this.disable_mam = true; // Don't do MAM queries for this box
|
||||
this.model.messages.on('add', this.onMessageAdded, this);
|
||||
@ -106,8 +107,7 @@
|
||||
unread_msgs: ''
|
||||
}
|
||||
));
|
||||
this.$content = this.$el.find('.chat-content');
|
||||
this.content = this.$content[0];
|
||||
this.content = this.el.querySelector('.chat-content');
|
||||
utils.refreshWebkit();
|
||||
return this;
|
||||
},
|
||||
|
@ -36,7 +36,7 @@
|
||||
//
|
||||
// New functions which don't exist yet can also be added.
|
||||
ChatBox: {
|
||||
getMessageAttributes ($message, $delay, original_stanza) {
|
||||
getMessageAttributes (message, delay, original_stanza) {
|
||||
const attrs = this.__super__.getMessageAttributes.apply(this, arguments);
|
||||
const result = sizzle(`stanza-id[xmlns="${Strophe.NS.SID}"]`, original_stanza).pop();
|
||||
if (!_.isUndefined(result)) {
|
||||
@ -50,7 +50,7 @@
|
||||
render () {
|
||||
const result = this.__super__.render.apply(this, arguments);
|
||||
if (!this.disable_mam) {
|
||||
this.$content.on('scroll', _.debounce(this.onScroll.bind(this), 100));
|
||||
this.content.addEventListener('scroll', _.debounce(this.onScroll.bind(this), 100));
|
||||
}
|
||||
return result;
|
||||
},
|
||||
@ -194,7 +194,7 @@
|
||||
renderChatArea () {
|
||||
const result = this.__super__.renderChatArea.apply(this, arguments);
|
||||
if (!this.disable_mam) {
|
||||
this.$content.on('scroll', _.debounce(this.onScroll.bind(this), 100));
|
||||
this.content.addEventListener('scroll', _.debounce(this.onScroll.bind(this), 100));
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
@ -158,9 +158,9 @@
|
||||
if (ev && ev.preventDefault) { ev.preventDefault(); }
|
||||
// save the scroll position to restore it on maximize
|
||||
if (this.model.collection && this.model.collection.browserStorage) {
|
||||
this.model.save({'scroll': this.$content.scrollTop()});
|
||||
this.model.save({'scroll': this.content.scrollTop});
|
||||
} else {
|
||||
this.model.set({'scroll': this.$content.scrollTop()});
|
||||
this.model.set({'scroll': this.content.scrollTop});
|
||||
}
|
||||
this.setChatState(_converse.INACTIVE).model.minimize();
|
||||
this.hide();
|
||||
|
@ -11,7 +11,6 @@
|
||||
*/
|
||||
(function (root, factory) {
|
||||
define([
|
||||
"jquery.noconflict",
|
||||
"form-utils",
|
||||
"converse-core",
|
||||
"lodash.fp",
|
||||
@ -42,7 +41,6 @@
|
||||
"backbone.vdomview"
|
||||
], factory);
|
||||
}(this, function (
|
||||
$,
|
||||
u,
|
||||
converse,
|
||||
fp,
|
||||
@ -439,6 +437,7 @@
|
||||
},
|
||||
|
||||
initialize () {
|
||||
this.scrollDown = _.debounce(this._scrollDown, 250);
|
||||
this.markScrolled = _.debounce(this._markScrolled, 100);
|
||||
|
||||
this.model.messages.on('add', this.onMessageAdded, this);
|
||||
@ -501,7 +500,6 @@
|
||||
container_el.insertAdjacentElement('beforeend', this.occupantsview.el);
|
||||
this.renderToolbar(tpl_chatroom_toolbar);
|
||||
this.content = this.el.querySelector('.chat-content');
|
||||
this.$content = $(this.content);
|
||||
this.toggleOccupants(null, true);
|
||||
}
|
||||
return this;
|
||||
|
@ -63,12 +63,12 @@
|
||||
} else {
|
||||
value = field.value;
|
||||
}
|
||||
return u.stringToDOM(
|
||||
return u.stringToNode(
|
||||
tpl_field({
|
||||
name: field.getAttribute('name'),
|
||||
value: value
|
||||
})
|
||||
)[0];
|
||||
);
|
||||
};
|
||||
|
||||
u.xForm2webForm = function (field, stanza, domain) {
|
||||
|
21
src/utils.js
21
src/utils.js
@ -402,15 +402,30 @@
|
||||
}
|
||||
};
|
||||
|
||||
u.stringToDOM = function (s) {
|
||||
/* Converts an HTML string into a DOM element.
|
||||
u.stringToNode = function (s) {
|
||||
/* Converts an HTML string into a DOM Node.
|
||||
* Expects that the HTML string has only one top-level element,
|
||||
* i.e. not multiple ones.
|
||||
*
|
||||
* Parameters:
|
||||
* (String) s - The HTML string
|
||||
*/
|
||||
var div = document.createElement('div');
|
||||
div.innerHTML = s;
|
||||
return div.childNodes;
|
||||
return div.firstChild;
|
||||
};
|
||||
|
||||
u.stringToElement = function (s) {
|
||||
/* Converts an HTML string into a DOM element.
|
||||
* Expects that the HTML string has only one top-level element,
|
||||
* i.e. not multiple ones.
|
||||
*
|
||||
* Parameters:
|
||||
* (String) s - The HTML string
|
||||
*/
|
||||
var div = document.createElement('div');
|
||||
div.innerHTML = s;
|
||||
return div.firstElementChild;
|
||||
};
|
||||
|
||||
u.matchesSelector = function (el, selector) {
|
||||
|
Loading…
Reference in New Issue
Block a user