From 966669ebbc2a742a1c8c785634ea57dbbf61bb94 Mon Sep 17 00:00:00 2001 From: John Livingston Date: Mon, 5 Aug 2024 11:44:11 +0200 Subject: [PATCH] Search user messages WIP (#145) --- .../components/muc-mam-search-app-view.js | 11 +-- .../components/muc-mam-search-message-view.js | 82 +++++++++++++++++++ conversejs/custom/plugins/mam-search/index.js | 1 + .../styles/muc-mam-search-message.scss | 31 +++++++ .../templates/muc-mam-search-app.js | 15 ++-- .../templates/muc-mam-search-message.js | 31 +++++++ 6 files changed, 155 insertions(+), 16 deletions(-) create mode 100644 conversejs/custom/plugins/mam-search/components/muc-mam-search-message-view.js create mode 100644 conversejs/custom/plugins/mam-search/styles/muc-mam-search-message.scss create mode 100644 conversejs/custom/plugins/mam-search/templates/muc-mam-search-message.js diff --git a/conversejs/custom/plugins/mam-search/components/muc-mam-search-app-view.js b/conversejs/custom/plugins/mam-search/components/muc-mam-search-app-view.js index 3b3585f0..71150f30 100644 --- a/conversejs/custom/plugins/mam-search/components/muc-mam-search-app-view.js +++ b/conversejs/custom/plugins/mam-search/components/muc-mam-search-app-view.js @@ -3,7 +3,6 @@ // SPDX-License-Identifier: AGPL-3.0-only import { api } from '@converse/headless' -import { Collection } from '@converse/skeletor' import { parseMUCMessage } from '@converse/headless/plugins/muc/parsers.js' import { MUCApp } from '../../../shared/components/muc-app/index.js' import { tplMamSearchApp } from '../templates/muc-mam-search-app.js' @@ -42,12 +41,10 @@ export default class MUCMamSearchApp extends MUCApp { this.occupant = occupant // in case user did simultaneous requests const messages = await Promise.all(results.messages.map(s => parseMUCMessage(s, this.model))) - const col = new Collection() - for (const message of messages) { - // FIXME: this does not work for now, the collection is not properly initiated (no storage engine) - col.create(message) - } - this.results = col + // Note: we are not using MUCMessage objects, because we don't want the objects + // used here to interract with objects in the chat rooms. + // We could have a lot of unwanted sideeffects. + this.results = messages.reverse() }) } } diff --git a/conversejs/custom/plugins/mam-search/components/muc-mam-search-message-view.js b/conversejs/custom/plugins/mam-search/components/muc-mam-search-message-view.js new file mode 100644 index 00000000..60023641 --- /dev/null +++ b/conversejs/custom/plugins/mam-search/components/muc-mam-search-message-view.js @@ -0,0 +1,82 @@ +// SPDX-FileCopyrightText: 2024 John Livingston +// +// SPDX-License-Identifier: AGPL-3.0-only + +import { CustomElement } from 'shared/components/element.js' +import { tplMucMamSearchMessage } from '../templates/muc-mam-search-message.js' +import { api } from '@converse/headless' + +import '../styles/muc-mam-search-message.scss' + +export default class MUCMamSearchMessageView extends CustomElement { + static get properties () { + return { + message: { type: Object, attribute: true }, // /!\ this is not a model + mucModel: { type: Object, attribute: true }, + searchOccupantModel: { type: Object, attribute: true } + } + } + + async initialize () { + this.listenTo(this.mucModel, 'change', () => this.requestUpdate()) + this.listenTo(this.searchOccupantModel, 'change', () => this.requestUpdate()) + } + + render () { + return tplMucMamSearchMessage(this, this.mucModel, this.searchOccupantModel, this.message) + } + + getMessageOccupant () { + const occupants = this.mucModel?.occupants + if (!occupants?.findOccupant) { return undefined } + + const nick = this.message.nick + const jid = this.message.from + const occupantId = this.message.occupant_id + + if (!nick && !jid && !occupantId) { + return undefined + } + + if (occupantId) { + const o = occupants.findOccupant({ occupant_id: occupantId }) + if (o) { + return o + } + } + + if (jid) { + const o = occupants.findOccupant({ + jid, + nick + }) + if (o) { + return o + } + } + + // If we don't find it, maybe it is a user that has spoken a long time ago (or never spoked). + // In such case, we must create a dummy occupant: + const o = occupants.create({ + nick, + occupant_id: occupantId, + jid + }) + return o + } + + getDateTime () { + if (!this.message.time) { + return undefined + } + try { + const d = new Date(this.message.time) + return d.toLocaleDateString() + ' - ' + d.toLocaleTimeString() + } catch (err) { + console.log(err) + return undefined + } + } +} + +api.elements.define('livechat-converse-muc-mam-search-message', MUCMamSearchMessageView) diff --git a/conversejs/custom/plugins/mam-search/index.js b/conversejs/custom/plugins/mam-search/index.js index d5efd510..edaf3faa 100644 --- a/conversejs/custom/plugins/mam-search/index.js +++ b/conversejs/custom/plugins/mam-search/index.js @@ -8,6 +8,7 @@ import mamSearchApi from './api.js' import './components/muc-mam-search-app-view.js' import './components/muc-mam-search-occupant-view.js' +import './components/muc-mam-search-message-view.js' converse.plugins.add('livechat-converse-mam-search', { dependencies: ['converse-muc', 'converse-muc-views'], diff --git a/conversejs/custom/plugins/mam-search/styles/muc-mam-search-message.scss b/conversejs/custom/plugins/mam-search/styles/muc-mam-search-message.scss new file mode 100644 index 00000000..2001bad6 --- /dev/null +++ b/conversejs/custom/plugins/mam-search/styles/muc-mam-search-message.scss @@ -0,0 +1,31 @@ +/* + * SPDX-FileCopyrightText: 2024 John Livingston + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +.conversejs { + livechat-converse-muc-mam-search-message { + border: 1px solid var(--chatroom-head-bg-color); + border-radius: 4px; + display: block; + margin: 0.25em 0; + padding: 0.25em; + width: 100%; + + converse-rich-text { + color: var(--message-text-color); + font-size: var(--message-font-size); + padding: 0; + white-space: pre-wrap; + word-wrap: break-word; + word-break: break-word; + } + + .livechat-message-date { + font-size: 0.75em; + list-style: none; + text-align: right; + } + } +} diff --git a/conversejs/custom/plugins/mam-search/templates/muc-mam-search-app.js b/conversejs/custom/plugins/mam-search/templates/muc-mam-search-app.js index c4ee4371..8e3a9e10 100644 --- a/conversejs/custom/plugins/mam-search/templates/muc-mam-search-app.js +++ b/conversejs/custom/plugins/mam-search/templates/muc-mam-search-app.js @@ -19,22 +19,19 @@ function tplContent (el, mucModel, occupantModel) { ` : '' } +
${ el.results - ? repeat(el.results, (message) => message.id, message => tplMessage(message)) + ? repeat(el.results, (message) => message.id, message => { + return html`` + }) : html`` } ` } -function tplMessage (model) { - return html` - ` -} - export function tplMamSearchApp (el, mucModel, occupantModel) { if (!mucModel) { // should not happen diff --git a/conversejs/custom/plugins/mam-search/templates/muc-mam-search-message.js b/conversejs/custom/plugins/mam-search/templates/muc-mam-search-message.js new file mode 100644 index 00000000..48f5b5a5 --- /dev/null +++ b/conversejs/custom/plugins/mam-search/templates/muc-mam-search-message.js @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: 2024 John Livingston +// +// SPDX-License-Identifier: AGPL-3.0-only + +import { html } from 'lit' + +/** + * Renders the message as a search result. + * @param el The message element + * @param mucModel The MUC model + * @param searchOccupantModel The model of the occupant for which we are searching + * @param message The message (warning: this is not a model) + * @returns TemplateResult (or equivalent) + */ +export function tplMucMamSearchMessage (el, mucModel, searchOccupantModel, message) { + const occupant = el.getMessageOccupant() + return html` + ${ + occupant + ? html` + ` + : '' + } + + +
${el.getDateTime()}
` +}