message-history.js 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. import "./message";
  2. import dayjs from 'dayjs';
  3. import tpl_new_day from "./templates/new-day.js";
  4. import { CustomElement } from 'shared/components/element.js';
  5. import { _converse, api } from "@converse/headless/core";
  6. import { html } from 'lit';
  7. import { repeat } from 'lit/directives/repeat.js';
  8. // Return a TemplateResult indicating a new day if the passed in message is
  9. // more than a day later than its predecessor.
  10. function getDayIndicator (model) {
  11. const models = model.collection.models;
  12. const idx = models.indexOf(model);
  13. const prev_model = models[idx-1];
  14. if (!prev_model || dayjs(model.get('time')).isAfter(dayjs(prev_model.get('time')), 'day')) {
  15. const day_date = dayjs(model.get('time')).startOf('day');
  16. return tpl_new_day({
  17. 'type': 'date',
  18. 'time': day_date.toISOString(),
  19. 'datestring': day_date.format("dddd MMM Do YYYY")
  20. });
  21. }
  22. }
  23. // This is set to _converse so that it can be overriden. An attempt was made to use
  24. // a hook instead, but hook returns a promise and it forces the asynchronicity up
  25. // to the render method.
  26. _converse.getHats = function (model) {
  27. if (model.get('type') === 'groupchat') {
  28. const allowed_hats = api.settings.get('muc_hats').filter(hat => hat).map((hat) => (hat.toLowerCase()));
  29. let vcard_roles = []
  30. if (allowed_hats.includes('vcard_roles')) {
  31. vcard_roles = model.vcard ? model.vcard.get('role') : null;
  32. vcard_roles = vcard_roles ? vcard_roles.split(',').filter(hat => hat).map((hat) => ({title: hat})) : [];
  33. }
  34. const muc_role = model.occupant ? [model.occupant.get('role')] : [];
  35. const muc_affiliation = model.occupant ? [model.occupant.get('affiliation')] : [];
  36. const affiliation_role_hats = [...muc_role, ...muc_affiliation]
  37. .filter(hat => hat).filter((hat) => (allowed_hats.includes(hat.toLowerCase())))
  38. .map((hat) => ({title: hat}));
  39. const hats = allowed_hats.includes('xep317') ? model.occupant?.get('hats') || [] : [];
  40. return [...hats, ...vcard_roles, ...affiliation_role_hats];
  41. }
  42. return [];
  43. }
  44. export default class MessageHistory extends CustomElement {
  45. static get properties () {
  46. return {
  47. model: { type: Object },
  48. messages: { type: Array }
  49. }
  50. }
  51. render () {
  52. const msgs = this.messages;
  53. return msgs.length ? html`${repeat(msgs, m => m.get('id'), m => this.renderMessage(m)) }` : '';
  54. }
  55. renderMessage (model) {
  56. if (model.get('dangling_retraction') || model.get('is_only_key')) {
  57. return '';
  58. }
  59. const day = getDayIndicator(model);
  60. const templates = day ? [day] : [];
  61. const message = html`<converse-chat-message
  62. jid="${this.model.get('jid')}"
  63. mid="${model.get('id')}"></converse-chat-message>`
  64. return [...templates, message];
  65. }
  66. }
  67. api.elements.define('converse-message-history', MessageHistory);