Share chat url

Modal for video owner (and instance's moderators) that allows to generate a link to the chat. So you can - for example - obtain the url to use for OBS integration.
WIP
This commit is contained in:
John Livingston
2021-12-14 15:41:34 +01:00
parent 148b28ef84
commit 566681150b
8 changed files with 323 additions and 68 deletions

View File

@ -1,7 +1,10 @@
import type { ChatType } from 'shared/lib/types'
import { videoHasWebchat } from 'shared/lib/video'
import { AutoColors, isAutoColorsAvailable, areAutoColorsValid } from 'shared/lib/autocolors'
import { closeSVG, openBlankChatSVG, openChatSVG, SVGButton } from './videowatch/buttons'
import { logger } from './videowatch/logger'
import { closeSVG, openBlankChatSVG, openChatSVG, shareChatUrlSVG } from './videowatch/buttons'
import { displayButton, displayButtonOptions } from './videowatch/button'
import { shareChatUrl } from './videowatch/share'
interface VideoWatchLoadedHookOptions {
videojs: any
@ -9,14 +12,8 @@ interface VideoWatchLoadedHookOptions {
playlist?: any
}
function register ({ registerHook, peertubeHelpers }: RegisterOptions): void {
const logger = {
log: (s: string) => console.log('[peertube-plugin-livechat] ' + s),
info: (s: string) => console.info('[peertube-plugin-livechat] ' + s),
error: (s: string) => console.error('[peertube-plugin-livechat] ' + s),
warn: (s: string) => console.warn('[peertube-plugin-livechat] ' + s)
}
function register (registerOptions: RegisterOptions): void {
const { registerHook, peertubeHelpers } = registerOptions
let settings: any = {}
function getBaseRoute (): string {
@ -125,58 +122,22 @@ function register ({ registerHook, peertubeHelpers }: RegisterOptions): void {
return autocolors
}
function displayButton (
buttonContainer: HTMLElement,
name: string,
label: string,
callback: () => void | boolean,
icon?: SVGButton,
additionalClasses?: string[]
): void {
const button = document.createElement('a')
button.classList.add(
'orange-button', 'peertube-button-link',
'peertube-plugin-livechat-button',
'peertube-plugin-livechat-button-' + name
)
if (additionalClasses) {
for (let i = 0; i < additionalClasses.length; i++) {
button.classList.add(additionalClasses[i])
}
}
button.onclick = callback
if (icon) {
try {
const svg = icon()
const tmp = document.createElement('span')
tmp.innerHTML = svg.trim()
const svgDom = tmp.firstChild
if (svgDom) {
button.prepend(svgDom)
}
} catch (err) {
logger.error('Failed to generate the ' + name + ' button: ' + (err as string))
}
button.setAttribute('title', label)
} else {
button.textContent = label
}
buttonContainer.append(button)
}
async function insertChatDom (container: HTMLElement, video: Video, showOpenBlank: boolean): Promise<void> {
async function insertChatDom (
container: HTMLElement, video: Video, showOpenBlank: boolean, showShareUrlButton: boolean
): Promise<void> {
logger.log('Adding livechat in the DOM...')
const p = new Promise<void>((resolve, reject) => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
Promise.all([
peertubeHelpers.translate('Open chat'),
peertubeHelpers.translate('Open chat in a new window'),
peertubeHelpers.translate('Close chat')
peertubeHelpers.translate('Close chat'),
peertubeHelpers.translate('Share link')
]).then(labels => {
const labelOpen = labels[0]
const labelOpenBlank = labels[1]
const labelClose = labels[2]
const labelShareUrl = labels[3]
const iframeUri = getIframeUri(video)
if (!iframeUri) {
@ -187,27 +148,66 @@ function register ({ registerHook, peertubeHelpers }: RegisterOptions): void {
buttonContainer.classList.add('peertube-plugin-livechat-buttons')
container.append(buttonContainer)
// Here are buttons that are magically merged
const groupButtons: displayButtonOptions[] = []
groupButtons.push({
buttonContainer,
name: 'open',
label: labelOpen,
callback: () => openChat(video),
icon: openChatSVG,
additionalClasses: []
})
if (showOpenBlank) {
displayButton(
buttonContainer, 'open',
labelOpen, () => openChat(video),
openChatSVG,
['peertube-plugin-livechat-multi-button-main']
)
displayButton(
buttonContainer, 'openblank',
labelOpenBlank, () => {
groupButtons.push({
buttonContainer,
name: 'openblank',
label: labelOpenBlank,
callback: () => {
closeChat()
window.open(iframeUri)
},
openBlankChatSVG,
['peertube-plugin-livechat-multi-button-secondary']
)
} else {
displayButton(buttonContainer, 'open', labelOpen, () => openChat(video), openChatSVG)
icon: openBlankChatSVG,
additionalClasses: []
})
}
if (showShareUrlButton) {
groupButtons.push({
buttonContainer,
name: 'shareurl',
label: labelShareUrl,
callback: () => {
shareChatUrl(registerOptions)
},
icon: shareChatUrlSVG,
additionalClasses: []
})
}
displayButton(buttonContainer, 'close', labelClose, () => closeChat(), closeSVG)
// If more than one groupButtons:
// - the first must have class 'peertube-plugin-livechat-multi-button-main'
// - middle ones must have 'peertube-plugin-livechat-multi-button-secondary'
// - the last must have 'peertube-plugin-livechat-multi-button-last-secondary'
if (groupButtons.length > 1) {
groupButtons[0].additionalClasses?.push('peertube-plugin-livechat-multi-button-main')
for (let i = 1; i < groupButtons.length - 1; i++) { // middle
groupButtons[i].additionalClasses?.push('peertube-plugin-livechat-multi-button-secondary')
}
groupButtons[groupButtons.length - 1]
.additionalClasses?.push('peertube-plugin-livechat-multi-button-last-secondary')
}
for (const button of groupButtons) {
displayButton(button)
}
displayButton({
buttonContainer,
name: 'close',
label: labelClose,
callback: () => closeChat(),
icon: closeSVG
})
resolve()
})
})
@ -301,7 +301,12 @@ function register ({ registerHook, peertubeHelpers }: RegisterOptions): void {
return
}
insertChatDom(container as HTMLElement, video, !!settings['chat-open-blank']).then(() => {
let showShareUrlButton: boolean = false
if (settings['chat-type'] === 'builtin-prosody') {
// FIXME: showShareUrlButton should only be true for video owner and instance moderators.
showShareUrlButton = true
}
insertChatDom(container as HTMLElement, video, !!settings['chat-open-blank'], showShareUrlButton).then(() => {
if (settings['chat-auto-display']) {
openChat(video)
} else if (container) {