Search user messages WIP (#145)
This commit is contained in:
parent
dd03075831
commit
4181661faf
@ -15,9 +15,9 @@ livechat-spinner,
|
|||||||
height: 48px;
|
height: 48px;
|
||||||
margin: 20px;
|
margin: 20px;
|
||||||
/* stylelint-disable-next-line custom-property-pattern */
|
/* 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 */
|
/* 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%;
|
border-radius: 50%;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
box-sizing: border-box;
|
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
|
// 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).
|
// (and i now there is some CSS bugs in the task list).
|
||||||
// Same for the moderator notes app.
|
// Same for the moderator notes app.
|
||||||
let enableTask = false
|
let enableApps = false
|
||||||
let enableModeratorNotes = false
|
|
||||||
if (chatIncludeMode === 'peertube-video' || chatIncludeMode === 'peertube-fullpage') {
|
if (chatIncludeMode === 'peertube-video' || chatIncludeMode === 'peertube-fullpage') {
|
||||||
enableTask = true
|
enableApps = true
|
||||||
enableModeratorNotes = true
|
|
||||||
} else if (
|
} else if (
|
||||||
chatIncludeMode === 'chat-only' &&
|
chatIncludeMode === 'chat-only' &&
|
||||||
usedLivechatToken &&
|
usedLivechatToken &&
|
||||||
!initConverseParams.transparent &&
|
!initConverseParams.transparent &&
|
||||||
!initConverseParams.forceReadonly
|
!initConverseParams.forceReadonly
|
||||||
) {
|
) {
|
||||||
enableTask = true
|
enableApps = true
|
||||||
enableModeratorNotes = true
|
|
||||||
}
|
}
|
||||||
if (enableTask) {
|
if (enableApps) {
|
||||||
params.livechat_task_app_enabled = true
|
params.livechat_task_app_enabled = true
|
||||||
params.livechat_task_app_restore = chatIncludeMode === 'peertube-fullpage' || chatIncludeMode === 'chat-only'
|
params.livechat_task_app_restore = chatIncludeMode === 'peertube-fullpage' || chatIncludeMode === 'chat-only'
|
||||||
}
|
|
||||||
if (enableModeratorNotes) {
|
|
||||||
params.livechat_note_app_enabled = true
|
params.livechat_note_app_enabled = true
|
||||||
params.livechat_note_app_restore = chatIncludeMode === 'peertube-fullpage' || chatIncludeMode === 'chat-only'
|
params.livechat_note_app_restore = chatIncludeMode === 'peertube-fullpage' || chatIncludeMode === 'chat-only'
|
||||||
|
params.livechat_mam_search_app_enabled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -95,6 +95,18 @@ async function query (options) {
|
|||||||
return { messages }
|
return { messages }
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
async function showMessagesFrom (occupant) {
|
||||||
query
|
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
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import { api, converse } from '../../../src/headless/index.js'
|
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 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', {
|
converse.plugins.add('livechat-converse-mam-search', {
|
||||||
dependencies: ['converse-muc', 'converse-muc-views'],
|
dependencies: ['converse-muc', 'converse-muc-views'],
|
||||||
@ -16,56 +18,13 @@ converse.plugins.add('livechat-converse-mam-search', {
|
|||||||
livechat_mam_search: mamSearchApi
|
livechat_mam_search: mamSearchApi
|
||||||
})
|
})
|
||||||
|
|
||||||
|
_converse.api.settings.extend({
|
||||||
|
livechat_mam_search_app_enabled: false
|
||||||
|
})
|
||||||
|
|
||||||
// Adding buttons on message:
|
// Adding buttons on message:
|
||||||
_converse.api.listen.on('getMessageActionButtons', getMessageActionButtons)
|
_converse.api.listen.on('getMessageActionButtons', getMessageActionButtons)
|
||||||
|
|
||||||
// FIXME: should we listen to any event (feature/affiliation change?, mam_enabled?) to refresh messageActionButtons?
|
// 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>`
|
? 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)}`
|
${tplMUCChatarea(o)}`
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,8 @@ const locKeys = [
|
|||||||
'moderator_note_search_for_participant',
|
'moderator_note_search_for_participant',
|
||||||
'moderator_note_filters',
|
'moderator_note_filters',
|
||||||
'moderator_note_original_nick',
|
'moderator_note_original_nick',
|
||||||
'search_occupant_message'
|
'search_occupant_message',
|
||||||
|
'message_search'
|
||||||
]
|
]
|
||||||
|
|
||||||
module.exports = locKeys
|
module.exports = locKeys
|
||||||
|
@ -605,4 +605,5 @@ moderator_note_search_for_participant: 'Search notes about this participant'
|
|||||||
moderator_note_filters: 'Search filters'
|
moderator_note_filters: 'Search filters'
|
||||||
moderator_note_original_nick: 'Nickname of the participant at the time of the note creation'
|
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…
x
Reference in New Issue
Block a user