Search user messages WIP (#145)
This commit is contained in:
parent
dd03075831
commit
4181661faf
@ -15,9 +15,9 @@ livechat-spinner,
|
||||
height: 48px;
|
||||
margin: 20px;
|
||||
/* stylelint-disable-next-line custom-property-pattern */
|
||||
border: 5px solid var(--greyBackgroundColor);
|
||||
border: 5px solid var(--greyBackgroundColor) !important; // !important is required for it to work in ConverseJS
|
||||
/* stylelint-disable-next-line custom-property-pattern */
|
||||
border-bottom-color: var(--mainColor);
|
||||
border-bottom-color: var(--mainColor) !important; // !important is required for it to work in ConverseJS
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
|
@ -220,27 +220,23 @@ async function initConverse (
|
||||
// Technically it would work in 'chat-only' mode, but i don't want to add too many things to test
|
||||
// (and i now there is some CSS bugs in the task list).
|
||||
// Same for the moderator notes app.
|
||||
let enableTask = false
|
||||
let enableModeratorNotes = false
|
||||
let enableApps = false
|
||||
if (chatIncludeMode === 'peertube-video' || chatIncludeMode === 'peertube-fullpage') {
|
||||
enableTask = true
|
||||
enableModeratorNotes = true
|
||||
enableApps = true
|
||||
} else if (
|
||||
chatIncludeMode === 'chat-only' &&
|
||||
usedLivechatToken &&
|
||||
!initConverseParams.transparent &&
|
||||
!initConverseParams.forceReadonly
|
||||
) {
|
||||
enableTask = true
|
||||
enableModeratorNotes = true
|
||||
enableApps = true
|
||||
}
|
||||
if (enableTask) {
|
||||
if (enableApps) {
|
||||
params.livechat_task_app_enabled = true
|
||||
params.livechat_task_app_restore = chatIncludeMode === 'peertube-fullpage' || chatIncludeMode === 'chat-only'
|
||||
}
|
||||
if (enableModeratorNotes) {
|
||||
params.livechat_note_app_enabled = true
|
||||
params.livechat_note_app_restore = chatIncludeMode === 'peertube-fullpage' || chatIncludeMode === 'chat-only'
|
||||
params.livechat_mam_search_app_enabled = true
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -95,6 +95,18 @@ async function query (options) {
|
||||
return { messages }
|
||||
}
|
||||
|
||||
export default {
|
||||
query
|
||||
async function showMessagesFrom (occupant) {
|
||||
const appElement = document.querySelector('livechat-converse-muc-mam-search-app')
|
||||
if (!appElement) {
|
||||
throw new Error('Cant find Search App Element')
|
||||
}
|
||||
appElement.searchFrom(occupant)
|
||||
await appElement.showApp()
|
||||
await appElement.updateComplete // waiting for the app to be open
|
||||
return appElement
|
||||
}
|
||||
|
||||
export default {
|
||||
query,
|
||||
showMessagesFrom
|
||||
}
|
||||
|
@ -0,0 +1,55 @@
|
||||
// SPDX-FileCopyrightText: 2024 John Livingston <https://www.john-livingston.fr/>
|
||||
//
|
||||
// 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'
|
||||
|
||||
/**
|
||||
* Custom Element to display the Mam Search Application.
|
||||
*/
|
||||
export default class MUCMamSearchApp extends MUCApp {
|
||||
restoreSettingName = undefined
|
||||
sessionStorageRestoreKey = undefined
|
||||
|
||||
static get properties () {
|
||||
return {
|
||||
model: { type: Object, attribute: true }, // the muc model
|
||||
occupant: { type: Object, attribute: true }, // the occupant to search (can be undefined if no current search)
|
||||
results: { type: Object, attribute: true } // a Collection with the results.
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
return tplMamSearchApp(this, this.model, this.occupant)
|
||||
}
|
||||
|
||||
searchFrom (occupant) {
|
||||
this.results = undefined
|
||||
this.occupant = occupant
|
||||
const p = api.livechat_mam_search.query({
|
||||
room: this.model.get('jid'),
|
||||
// FIXME: shouldn't we escape the nick? cant see any code that escapes it in Converse.
|
||||
from: occupant.get('from') || this.model.get('jid') + '/' + (occupant.get('nick') ?? ''),
|
||||
occupant_id: occupant.get('occupant_id')
|
||||
})
|
||||
|
||||
// don't wait the result to show something! (there will be a spinner)
|
||||
p.then(async (results) => {
|
||||
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
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
api.elements.define('livechat-converse-muc-mam-search-app', MUCMamSearchApp)
|
@ -0,0 +1,27 @@
|
||||
// SPDX-FileCopyrightText: 2024 John Livingston <https://www.john-livingston.fr/>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { CustomElement } from 'shared/components/element.js'
|
||||
import { tplMucMamSearchOccupant } from '../templates/muc-mam-search-occupant'
|
||||
import { api } from '@converse/headless'
|
||||
|
||||
import '../styles/muc-mam-search-occupant.scss'
|
||||
|
||||
export default class MUCMamSearchOccupantView extends CustomElement {
|
||||
static get properties () {
|
||||
return {
|
||||
model: { type: Object, attribute: true }
|
||||
}
|
||||
}
|
||||
|
||||
async initialize () {
|
||||
this.listenTo(this.model, 'change', () => this.requestUpdate())
|
||||
}
|
||||
|
||||
render () {
|
||||
return tplMucMamSearchOccupant(this, this.model)
|
||||
}
|
||||
}
|
||||
|
||||
api.elements.define('livechat-converse-muc-mam-search-occupant', MUCMamSearchOccupantView)
|
@ -3,9 +3,11 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { api, converse } from '../../../src/headless/index.js'
|
||||
import { XMLNS_MAM_SEARCH } from './constants.js'
|
||||
import { getMessageActionButtons } from './utils.js'
|
||||
import mamSearchApi from './api.js'
|
||||
import { __ } from 'i18n'
|
||||
|
||||
import './components/muc-mam-search-app-view.js'
|
||||
import './components/muc-mam-search-occupant-view.js'
|
||||
|
||||
converse.plugins.add('livechat-converse-mam-search', {
|
||||
dependencies: ['converse-muc', 'converse-muc-views'],
|
||||
@ -16,56 +18,13 @@ converse.plugins.add('livechat-converse-mam-search', {
|
||||
livechat_mam_search: mamSearchApi
|
||||
})
|
||||
|
||||
_converse.api.settings.extend({
|
||||
livechat_mam_search_app_enabled: false
|
||||
})
|
||||
|
||||
// Adding buttons on message:
|
||||
_converse.api.listen.on('getMessageActionButtons', getMessageActionButtons)
|
||||
|
||||
// FIXME: should we listen to any event (feature/affiliation change?, mam_enabled?) to refresh messageActionButtons?
|
||||
}
|
||||
})
|
||||
|
||||
function getMessageActionButtons (messageActionsEl, buttons) {
|
||||
const messageModel = messageActionsEl.model
|
||||
if (messageModel.get('type') !== 'groupchat') {
|
||||
// only on groupchat message.
|
||||
return buttons
|
||||
}
|
||||
|
||||
if (!messageModel.occupant) {
|
||||
return buttons
|
||||
}
|
||||
|
||||
const muc = messageModel.collection?.chatbox
|
||||
if (!muc) {
|
||||
return buttons
|
||||
}
|
||||
|
||||
if (!muc.features?.get?.(XMLNS_MAM_SEARCH)) {
|
||||
return buttons
|
||||
}
|
||||
|
||||
const myself = muc.getOwnOccupant()
|
||||
if (!myself || !['admin', 'owner'].includes(myself.get('affiliation'))) {
|
||||
return buttons
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
const i18nSearch = __(LOC_search_occupant_message)
|
||||
|
||||
buttons.push({
|
||||
i18n_text: i18nSearch,
|
||||
handler: async (ev) => {
|
||||
ev.preventDefault()
|
||||
console.log(await api.livechat_mam_search.query({
|
||||
room: muc.get('jid'),
|
||||
// FIXME: shouldn't we escape the nick? cant see any code that escapes it in Converse.
|
||||
from: messageModel.occupant.get('from') || muc.get('jid') + '/' + (messageModel.occupant.get('nick') ?? ''),
|
||||
occupant_id: messageModel.occupant.get('occupant_id')
|
||||
}))
|
||||
},
|
||||
button_class: '',
|
||||
icon_class: 'fa fa-magnifying-glass',
|
||||
name: 'muc-mam-search'
|
||||
})
|
||||
|
||||
return buttons
|
||||
}
|
||||
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 John Livingston <https://www.john-livingston.fr/>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
.conversejs {
|
||||
livechat-converse-muc-mam-search-occupant {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0.25em;
|
||||
|
||||
& > a {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
align-items: center;
|
||||
|
||||
span {
|
||||
font-weight: bold;
|
||||
margin-left: 0.5em;
|
||||
max-width: 200px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
& > ul {
|
||||
font-weight: lighter;
|
||||
font-size: 0.75em;
|
||||
list-style: none;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
// SPDX-FileCopyrightText: 2024 John Livingston <https://www.john-livingston.fr/>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { converseLocalizedHelpUrl } from '../../../shared/lib/help'
|
||||
import { tplMUCApp } from '../../../shared/components/muc-app/templates/muc-app.js'
|
||||
import { html } from 'lit'
|
||||
import { repeat } from 'lit/directives/repeat.js'
|
||||
import { __ } from 'i18n'
|
||||
|
||||
function tplContent (el, mucModel, occupantModel) {
|
||||
return html`
|
||||
${
|
||||
occupantModel
|
||||
? html`
|
||||
<livechat-converse-muc-mam-search-occupant
|
||||
.model=${occupantModel}
|
||||
></livechat-converse-muc-mam-search-occupant>
|
||||
`
|
||||
: ''
|
||||
}
|
||||
${
|
||||
el.results
|
||||
? repeat(el.results, (message) => message.id, message => tplMessage(message))
|
||||
: html`<livechat-spinner></livechat-spinner>`
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
function tplMessage (model) {
|
||||
return html`
|
||||
<converse-chat-message
|
||||
jid="${this.model.get('jid')}"
|
||||
mid="${model.get('id')}"
|
||||
></converse-chat-message>`
|
||||
}
|
||||
|
||||
export function tplMamSearchApp (el, mucModel, occupantModel) {
|
||||
if (!mucModel) {
|
||||
// should not happen
|
||||
return html``
|
||||
}
|
||||
|
||||
if (!el.show) {
|
||||
return html``
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
const i18nSearch = __(LOC_message_search)
|
||||
// eslint-disable-next-line no-undef
|
||||
const i18nHelp = __(LOC_online_help)
|
||||
const helpUrl = converseLocalizedHelpUrl({
|
||||
page: 'documentation/user/streamers/moderation'
|
||||
})
|
||||
|
||||
return tplMUCApp(
|
||||
el,
|
||||
i18nSearch,
|
||||
helpUrl,
|
||||
i18nHelp,
|
||||
tplContent(el, mucModel, occupantModel)
|
||||
)
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
// SPDX-FileCopyrightText: 2024 John Livingston <https://www.john-livingston.fr/>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { html } from 'lit'
|
||||
import { api } from '@converse/headless'
|
||||
import { getAuthorStyle } from '../../../../src/utils/color.js'
|
||||
import { __ } from 'i18n'
|
||||
|
||||
export function tplMucMamSearchOccupant (el, occupant) {
|
||||
const authorStyle = getAuthorStyle(occupant)
|
||||
const jid = occupant.get('jid')
|
||||
const occupantId = occupant.get('occupant_id')
|
||||
|
||||
return html`
|
||||
<a @click=${(ev) => {
|
||||
api.modal.show('converse-muc-occupant-modal', { model: occupant }, ev)
|
||||
}}>
|
||||
<converse-avatar
|
||||
.model=${occupant}
|
||||
class="avatar chat-msg__avatar"
|
||||
name="${occupant.getDisplayName()}"
|
||||
nonce=${occupant.vcard?.get('vcard_updated')}
|
||||
height="30" width="30"></converse-avatar>
|
||||
|
||||
<span style=${authorStyle}>${occupant.getDisplayName()}</span>
|
||||
</a>
|
||||
<ul aria-hidden="true">
|
||||
${jid ? html`<li title=${__('XMPP Address')}>${jid}</li>` : ''}
|
||||
${occupantId ? html`<li title=${__('Occupant Id')}>${occupantId}</li>` : ''}
|
||||
</ul>`
|
||||
}
|
57
conversejs/custom/plugins/mam-search/utils.js
Normal file
57
conversejs/custom/plugins/mam-search/utils.js
Normal file
@ -0,0 +1,57 @@
|
||||
// SPDX-FileCopyrightText: 2024 John Livingston <https://www.john-livingston.fr/>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { api } from '../../../src/headless/index.js'
|
||||
import { XMLNS_MAM_SEARCH } from './constants.js'
|
||||
import { __ } from 'i18n'
|
||||
|
||||
function getMessageActionButtons (messageActionsEl, buttons) {
|
||||
const messageModel = messageActionsEl.model
|
||||
if (!api.settings.get('livechat_mam_search_app_enabled')) {
|
||||
return buttons
|
||||
}
|
||||
|
||||
if (messageModel.get('type') !== 'groupchat') {
|
||||
// only on groupchat message.
|
||||
return buttons
|
||||
}
|
||||
|
||||
if (!messageModel.occupant) {
|
||||
return buttons
|
||||
}
|
||||
|
||||
const muc = messageModel.collection?.chatbox
|
||||
if (!muc) {
|
||||
return buttons
|
||||
}
|
||||
|
||||
if (!muc.features?.get?.(XMLNS_MAM_SEARCH)) {
|
||||
return buttons
|
||||
}
|
||||
|
||||
const myself = muc.getOwnOccupant()
|
||||
if (!myself || !['admin', 'owner'].includes(myself.get('affiliation'))) {
|
||||
return buttons
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
const i18nSearch = __(LOC_search_occupant_message)
|
||||
|
||||
buttons.push({
|
||||
i18n_text: i18nSearch,
|
||||
handler: async (ev) => {
|
||||
ev.preventDefault()
|
||||
api.livechat_mam_search.showMessagesFrom(messageModel.occupant)
|
||||
},
|
||||
button_class: '',
|
||||
icon_class: 'fa fa-magnifying-glass',
|
||||
name: 'muc-mam-search'
|
||||
})
|
||||
|
||||
return buttons
|
||||
}
|
||||
|
||||
export {
|
||||
getMessageActionButtons
|
||||
}
|
@ -18,5 +18,10 @@ export default (o) => {
|
||||
? html`<livechat-converse-muc-note-app .model=${o.model}></livechat-converse-muc-note-app>`
|
||||
: ''
|
||||
}
|
||||
${
|
||||
o?.model && api.settings.get('livechat_mam_search_app_enabled')
|
||||
? html`<livechat-converse-muc-mam-search-app .model=${o.model}></livechat-converse-muc-mam-search-app>`
|
||||
: ''
|
||||
}
|
||||
${tplMUCChatarea(o)}`
|
||||
}
|
||||
|
@ -60,7 +60,8 @@ const locKeys = [
|
||||
'moderator_note_search_for_participant',
|
||||
'moderator_note_filters',
|
||||
'moderator_note_original_nick',
|
||||
'search_occupant_message'
|
||||
'search_occupant_message',
|
||||
'message_search'
|
||||
]
|
||||
|
||||
module.exports = locKeys
|
||||
|
@ -605,4 +605,5 @@ moderator_note_search_for_participant: 'Search notes about this participant'
|
||||
moderator_note_filters: 'Search filters'
|
||||
moderator_note_original_nick: 'Nickname of the participant at the time of the note creation'
|
||||
|
||||
search_occupant_message: 'Search all message from this participant'
|
||||
search_occupant_message: 'Search all messages from this participant'
|
||||
message_search: 'Message search'
|
Loading…
Reference in New Issue
Block a user