Files
tryton/sao/src/chat.js
T
Cédric Krier 78b475740b Replace notify method by binded version in constructor of chat and notification menu
We need to keep a reference to the binded method registered to be able to
unregister it.

Closes #14425
2025-12-16 01:10:47 +01:00

204 lines
7.2 KiB
JavaScript

/* This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. */
(function() {
'use strict';
class _Chat {
constructor(record) {
this.notify = this.notify.bind(this);
this.record = record;
Sao.Bus.register(`chat:${this.record}`, this.notify);
this.el = this.__build();
}
unregister() {
Sao.Bus.unregister(`chat:${this.record}`, this.notify);
}
send_message(message, internal) {
return Sao.rpc({
'method': 'model.ir.chat.channel.post',
'params': [this.record, message, internal ? 'internal' : 'public', {}],
}, Sao.Session.current_session)
}
get_messages() {
return Sao.rpc({
'method': 'model.ir.chat.channel.get',
'params': [this.record, {}],
}, Sao.Session.current_session);
}
notify(message) {
this.refresh();
}
refresh() {
let prm = this.get_messages();
prm.done((posts) => {
this._messages.empty();
for (let post of posts) {
this._messages.append(this.create_message(post));
}
let messages = this._messages[this._messages.length - 1];
messages.scrollTop = messages.scrollHeight;
});
}
__build() {
let el = jQuery('<div/>', {
'class': 'chat',
});
let btn_group = jQuery('<div/>', {
'class': 'btn-group',
'role': 'group',
}).appendTo(el);
let subscribe_btn = jQuery('<button/>', {
'class': 'btn btn-default pull-right',
'type': 'button',
'title': Sao.i18n.gettext("Toggle notification"),
}).append(Sao.common.ICONFACTORY.get_icon_img(
'tryton-notification'))
.appendTo(btn_group);
Sao.rpc({
'method': 'model.ir.chat.channel.get_followers',
'params': [this.record, {}],
}, Sao.Session.current_session).then((followers) => {
set_subscribe_state(~followers.users.indexOf(
Sao.Session.current_session.login));
})
let set_subscribe_state = (subscribed) => {
let img;
if (subscribed) {
img = 'tryton-notification-on';
subscribe_btn.addClass('active').off().click(unsubscribe);
} else {
img = 'tryton-notification-off';
subscribe_btn.removeClass('active').off().click(subscribe);
}
subscribe_btn.html(Sao.common.ICONFACTORY.get_icon_img(img));
}
let subscribe = () => {
let session = Sao.Session.current_session;
Sao.rpc({
'method': 'model.ir.chat.channel.subscribe',
'params': [this.record, {}],
}, session).then(() => {
set_subscribe_state(true);
})
};
let unsubscribe = () => {
let session = Sao.Session.current_session;
Sao.rpc({
'method': 'model.ir.chat.channel.unsubscribe',
'params': [this.record, {}],
}, session).then(() => {
set_subscribe_state(false);
})
};
this._messages = jQuery('<div/>', {
'class': 'chat-messages',
}).appendTo(jQuery('<div/>', {
'class': 'chat-messages-outer',
}).appendTo(el));
let input = jQuery('<textarea/>', {
'class': 'input-sm form-control',
'placeholder': Sao.i18n.gettext("Enter a message"),
});
let submit = jQuery('<button/>', {
'class': 'btn btn-block btn-default',
'type': 'submit',
'aria-label': Sao.i18n.gettext("Submit the message"),
'title': Sao.i18n.gettext("Send"),
'text': Sao.i18n.gettext("Send"),
});
let internal = jQuery('<input/>', {
'type': 'checkbox',
});
jQuery('<hr/>').appendTo(el);
let form = jQuery('<form/>')
.append(jQuery('<div/>', {
'class': 'form-group',
}).append(input))
.append(jQuery('<div/>', {
'class': 'checkbox',
}).append(jQuery('<label/>')
.append(internal)
.append(Sao.i18n.gettext("Make this an internal message"))))
.append(submit)
.appendTo(el);
let send = (evt) => {
evt.preventDefault();
submit.prop('disabled', true);
input.prop('disabled', true);
this.send_message(
input.val(),
internal.prop('checked')
).done(() => {
input.val('');
submit.prop('disabled', false);
input.prop('disabled', false);
input.trigger('focus');
internal.prop('checked', false);
if (!Sao.Bus.listening) {
this.refresh();
}
});
};
form.submit(send);
input.keypress((evt) => {
if ((evt.which == Sao.common.RETURN_KEYCODE) && evt.ctrlKey) {
evt.preventDefault();
form.submit();
}
});
return el;
}
create_message(message) {
let avatar_size = 32;
let timestamp = Sao.common.format_datetime(
Sao.common.date_format() + ' %X', message.timestamp);
let avatar_url = '';
if (message.avatar_url) {
let url = new URL(message.avatar_url, window.location);
url.searchParams.set('s', avatar_size);
avatar_url = url.href;
}
return jQuery('<div/>', {
'class': 'media chat-message',
}).append(jQuery('<div/>', {
'class': 'media-left',
}).append(jQuery('<img/>', {
'class': 'media-object img-circle chat-avatar',
'src': avatar_url,
'alt': message.author,
'style': `width: ${avatar_size}px; height: ${avatar_size}px;`,
}))).append(jQuery('<div/>', {
'class': 'media-body well well-sm',
}).append(jQuery('<h6/>', {
'class': 'media-heading',
}).text(message.author)
.append(jQuery('<small/>', {
'class': 'text-muted pull-right',
}).text(timestamp)))
.append(jQuery('<div/>', {
'class': `chat-content chat-content-${message.audience}`,
}).text(message.content)));
}
}
Sao.Chat = _Chat;
}());