XMPP client connection WIP:
Adding an option in the «share chat» dialog to display the XMPP room address.
This commit is contained in:
parent
4d9d9d39b0
commit
4a28991497
@ -109,7 +109,7 @@ table.peertube-plugin-livechat-prosody-list-rooms td {
|
|||||||
|
|
||||||
.peertube-plugin-livechat-shareurl-modal {
|
.peertube-plugin-livechat-shareurl-modal {
|
||||||
& > * {
|
& > * {
|
||||||
margin-top: 30px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.livechat-shareurl-copy {
|
.livechat-shareurl-copy {
|
||||||
@ -126,8 +126,10 @@ table.peertube-plugin-livechat-prosody-list-rooms td {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.livechat-shareurl-custom {
|
.livechat-shareurl-web-options,
|
||||||
input[type="checkbox"] {
|
.livechat-shareurl-xmpp-options {
|
||||||
|
input[type="checkbox"],
|
||||||
|
input[type="radio"] {
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,18 +137,32 @@ table.peertube-plugin-livechat-prosody-list-rooms td {
|
|||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.livechat-shareurl-custom-readonly-options {
|
.livechat-shareurl-web-options-readonly {
|
||||||
margin-left: 40px;
|
margin-left: 40px;
|
||||||
|
|
||||||
& > * {
|
& > * {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.livechat-shareurl-custom-readonly-disabled {
|
&.livechat-shareurl-web-options-readonly-disabled {
|
||||||
label {
|
label {
|
||||||
color: var(--gray-dark);
|
color: var(--gray-dark);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.livechat-shareurl-protocol {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row wrap;
|
||||||
|
column-gap: 30px;
|
||||||
|
|
||||||
|
input[type="radio"] {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.livechat-shareurl-tips {
|
||||||
|
min-height: 60px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import type { RegisterClientOptions } from '@peertube/peertube-types/client'
|
import type { RegisterClientOptions } from '@peertube/peertube-types/client'
|
||||||
import type { Video } from '@peertube/peertube-types'
|
import type { Video } from '@peertube/peertube-types'
|
||||||
import { logger } from './logger'
|
import { logger } from './logger'
|
||||||
import { getIframeUri, UriOptions } from './uri'
|
import { getIframeUri, getXMPPUri, UriOptions } from './uri'
|
||||||
import { isAutoColorsAvailable } from 'shared/lib/autocolors'
|
import { isAutoColorsAvailable } from 'shared/lib/autocolors'
|
||||||
|
|
||||||
interface ShareForm {
|
interface ShareForm {
|
||||||
@ -14,6 +14,10 @@ interface ShareForm {
|
|||||||
readonlyOptions: HTMLElement
|
readonlyOptions: HTMLElement
|
||||||
autoColors?: HTMLInputElement
|
autoColors?: HTMLInputElement
|
||||||
generateIframe: HTMLInputElement
|
generateIframe: HTMLInputElement
|
||||||
|
divTips: HTMLElement
|
||||||
|
radioProtocolWeb?: HTMLInputElement
|
||||||
|
radioProtocolXMPP?: HTMLInputElement
|
||||||
|
divWebOptions: HTMLDivElement
|
||||||
}
|
}
|
||||||
|
|
||||||
async function shareChatUrl (registerOptions: RegisterClientOptions, settings: any, video: Video): Promise<void> {
|
async function shareChatUrl (registerOptions: RegisterClientOptions, settings: any, video: Video): Promise<void> {
|
||||||
@ -21,10 +25,13 @@ async function shareChatUrl (registerOptions: RegisterClientOptions, settings: a
|
|||||||
|
|
||||||
const [
|
const [
|
||||||
labelShare,
|
labelShare,
|
||||||
|
labelWeb,
|
||||||
|
labelXMPP,
|
||||||
|
labelXMPPTips,
|
||||||
labelReadonly,
|
labelReadonly,
|
||||||
labelWithscroll,
|
labelWithscroll,
|
||||||
labelTransparent,
|
labelTransparent,
|
||||||
tipsOBS,
|
labelOBSTips,
|
||||||
labelCopy,
|
labelCopy,
|
||||||
labelCopied,
|
labelCopied,
|
||||||
labelError,
|
labelError,
|
||||||
@ -34,6 +41,10 @@ async function shareChatUrl (registerOptions: RegisterClientOptions, settings: a
|
|||||||
labelChatFor
|
labelChatFor
|
||||||
] = await Promise.all([
|
] = await Promise.all([
|
||||||
peertubeHelpers.translate('Share chat link'),
|
peertubeHelpers.translate('Share chat link'),
|
||||||
|
peertubeHelpers.translate('Web'),
|
||||||
|
peertubeHelpers.translate('Connect using XMPP'),
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
|
peertubeHelpers.translate('You can connect to the room using an external XMPP account, and your favorite XMPP client.'),
|
||||||
peertubeHelpers.translate('Read-only'),
|
peertubeHelpers.translate('Read-only'),
|
||||||
peertubeHelpers.translate('Show the scrollbar'),
|
peertubeHelpers.translate('Show the scrollbar'),
|
||||||
peertubeHelpers.translate('Transparent background (for stream integration, with OBS for example)'),
|
peertubeHelpers.translate('Transparent background (for stream integration, with OBS for example)'),
|
||||||
@ -79,24 +90,52 @@ async function shareChatUrl (registerOptions: RegisterClientOptions, settings: a
|
|||||||
divShareString.append(openButton)
|
divShareString.append(openButton)
|
||||||
container.append(divShareString)
|
container.append(divShareString)
|
||||||
|
|
||||||
|
let radioProtocolWeb
|
||||||
|
let radioProtocolXMPP
|
||||||
|
if (settings['prosody-room-allow-s2s']) {
|
||||||
|
const protocolContainer = document.createElement('div')
|
||||||
|
protocolContainer.classList.add('livechat-shareurl-protocol')
|
||||||
|
|
||||||
|
radioProtocolWeb = document.createElement('input')
|
||||||
|
radioProtocolWeb.setAttribute('type', 'radio')
|
||||||
|
radioProtocolWeb.setAttribute('value', 'web')
|
||||||
|
radioProtocolWeb.setAttribute('name', 'protocol')
|
||||||
|
const radioProtocolWebLabel = document.createElement('label')
|
||||||
|
radioProtocolWebLabel.textContent = labelWeb
|
||||||
|
radioProtocolWebLabel.prepend(radioProtocolWeb)
|
||||||
|
protocolContainer.append(radioProtocolWebLabel)
|
||||||
|
|
||||||
|
radioProtocolXMPP = document.createElement('input')
|
||||||
|
radioProtocolXMPP.setAttribute('type', 'radio')
|
||||||
|
radioProtocolXMPP.setAttribute('value', 'xmpp')
|
||||||
|
radioProtocolXMPP.setAttribute('name', 'protocol')
|
||||||
|
const radioProtocolXMPPLabel = document.createElement('label')
|
||||||
|
radioProtocolXMPPLabel.textContent = labelXMPP
|
||||||
|
radioProtocolXMPPLabel.prepend(radioProtocolXMPP)
|
||||||
|
protocolContainer.append(radioProtocolXMPPLabel)
|
||||||
|
|
||||||
|
container.append(protocolContainer)
|
||||||
|
}
|
||||||
|
|
||||||
const divTips = document.createElement('div')
|
const divTips = document.createElement('div')
|
||||||
divTips.textContent = tipsOBS
|
divTips.textContent = ''
|
||||||
|
divTips.classList.add('livechat-shareurl-tips')
|
||||||
container.append(divTips)
|
container.append(divTips)
|
||||||
|
|
||||||
const divCustom = document.createElement('div')
|
const divWebOptions = document.createElement('div')
|
||||||
divCustom.classList.add('livechat-shareurl-custom')
|
divWebOptions.classList.add('livechat-shareurl-web-options')
|
||||||
container.append(divCustom)
|
container.append(divWebOptions)
|
||||||
|
|
||||||
const readonly = document.createElement('input')
|
const readonly = document.createElement('input')
|
||||||
readonly.setAttribute('type', 'checkbox')
|
readonly.setAttribute('type', 'checkbox')
|
||||||
const readonlyLabelEl = document.createElement('label')
|
const readonlyLabelEl = document.createElement('label')
|
||||||
readonlyLabelEl.textContent = labelReadonly
|
readonlyLabelEl.textContent = labelReadonly
|
||||||
readonlyLabelEl.prepend(readonly)
|
readonlyLabelEl.prepend(readonly)
|
||||||
divCustom.append(readonlyLabelEl)
|
divWebOptions.append(readonlyLabelEl)
|
||||||
|
|
||||||
const readonlyOptions = document.createElement('div')
|
const readonlyOptions = document.createElement('div')
|
||||||
readonlyOptions.classList.add('livechat-shareurl-custom-readonly-options')
|
readonlyOptions.classList.add('livechat-shareurl-web-options-readonly')
|
||||||
divCustom.append(readonlyOptions)
|
divWebOptions.append(readonlyOptions)
|
||||||
|
|
||||||
const withscroll = document.createElement('input')
|
const withscroll = document.createElement('input')
|
||||||
withscroll.setAttribute('type', 'checkbox')
|
withscroll.setAttribute('type', 'checkbox')
|
||||||
@ -119,7 +158,7 @@ async function shareChatUrl (registerOptions: RegisterClientOptions, settings: a
|
|||||||
autoColors = document.createElement('input')
|
autoColors = document.createElement('input')
|
||||||
autoColors.setAttribute('type', 'checkbox')
|
autoColors.setAttribute('type', 'checkbox')
|
||||||
label.prepend(autoColors)
|
label.prepend(autoColors)
|
||||||
divCustom.append(label)
|
divWebOptions.append(label)
|
||||||
}
|
}
|
||||||
|
|
||||||
const generateIframe = document.createElement('input')
|
const generateIframe = document.createElement('input')
|
||||||
@ -127,7 +166,18 @@ async function shareChatUrl (registerOptions: RegisterClientOptions, settings: a
|
|||||||
const generateIframeLabelEl = document.createElement('label')
|
const generateIframeLabelEl = document.createElement('label')
|
||||||
generateIframeLabelEl.textContent = labelGenerateIframe
|
generateIframeLabelEl.textContent = labelGenerateIframe
|
||||||
generateIframeLabelEl.prepend(generateIframe)
|
generateIframeLabelEl.prepend(generateIframe)
|
||||||
divCustom.append(generateIframeLabelEl)
|
divWebOptions.append(generateIframeLabelEl)
|
||||||
|
|
||||||
|
if (radioProtocolWeb) {
|
||||||
|
radioProtocolWeb.onclick = () => {
|
||||||
|
renderContent(container)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (radioProtocolXMPP) {
|
||||||
|
radioProtocolXMPP.onclick = () => {
|
||||||
|
renderContent(container)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
readonly.onclick = () => {
|
readonly.onclick = () => {
|
||||||
renderContent(container)
|
renderContent(container)
|
||||||
@ -164,7 +214,7 @@ async function shareChatUrl (registerOptions: RegisterClientOptions, settings: a
|
|||||||
|
|
||||||
openButton.onclick = () => {
|
openButton.onclick = () => {
|
||||||
// Don't open the url if it is an iframe!
|
// Don't open the url if it is an iframe!
|
||||||
if (shareString.value.startsWith('http')) {
|
if (shareString.value.startsWith('http') || shareString.value.startsWith('xmpp')) {
|
||||||
window.open(shareString.value)
|
window.open(shareString.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -178,7 +228,11 @@ async function shareChatUrl (registerOptions: RegisterClientOptions, settings: a
|
|||||||
transparent,
|
transparent,
|
||||||
readonlyOptions,
|
readonlyOptions,
|
||||||
autoColors,
|
autoColors,
|
||||||
generateIframe
|
generateIframe,
|
||||||
|
radioProtocolWeb,
|
||||||
|
radioProtocolXMPP,
|
||||||
|
divWebOptions,
|
||||||
|
divTips
|
||||||
}
|
}
|
||||||
restore(form)
|
restore(form)
|
||||||
}
|
}
|
||||||
@ -190,6 +244,16 @@ async function shareChatUrl (registerOptions: RegisterClientOptions, settings: a
|
|||||||
ignoreAutoColors: form.autoColors ? !form.autoColors.checked : true,
|
ignoreAutoColors: form.autoColors ? !form.autoColors.checked : true,
|
||||||
permanent: true
|
permanent: true
|
||||||
}
|
}
|
||||||
|
if (form.radioProtocolXMPP?.checked) {
|
||||||
|
// To minimize the height gap between the 2 modes,
|
||||||
|
// and prevent the dialog to resize and move too much,
|
||||||
|
// we use visibility instead of display
|
||||||
|
form.divTips.textContent = labelXMPPTips
|
||||||
|
form.divWebOptions.style.visibility = 'hidden'
|
||||||
|
} else {
|
||||||
|
form.divTips.textContent = labelOBSTips
|
||||||
|
form.divWebOptions.style.visibility = 'visible'
|
||||||
|
}
|
||||||
if (form.readonly.checked) {
|
if (form.readonly.checked) {
|
||||||
if (form.withscroll.checked) {
|
if (form.withscroll.checked) {
|
||||||
uriOptions.readonly = true
|
uriOptions.readonly = true
|
||||||
@ -201,28 +265,35 @@ async function shareChatUrl (registerOptions: RegisterClientOptions, settings: a
|
|||||||
}
|
}
|
||||||
form.withscroll.disabled = false
|
form.withscroll.disabled = false
|
||||||
form.transparent.disabled = false
|
form.transparent.disabled = false
|
||||||
form.readonlyOptions.classList.remove('livechat-shareurl-custom-readonly-disabled')
|
form.readonlyOptions.classList.remove('livechat-shareurl-web-options-readonly-disabled')
|
||||||
} else {
|
} else {
|
||||||
form.withscroll.disabled = true
|
form.withscroll.disabled = true
|
||||||
form.transparent.disabled = true
|
form.transparent.disabled = true
|
||||||
form.readonlyOptions.classList.add('livechat-shareurl-custom-readonly-disabled')
|
form.readonlyOptions.classList.add('livechat-shareurl-web-options-readonly-disabled')
|
||||||
}
|
}
|
||||||
let shareStringValue = getIframeUri(registerOptions, settings, video, uriOptions)
|
let shareStringValue
|
||||||
if (form.generateIframe.checked) {
|
if (!form.radioProtocolXMPP?.checked) {
|
||||||
form.openButton.disabled = true
|
shareStringValue = getIframeUri(registerOptions, settings, video, uriOptions)
|
||||||
if (shareStringValue) {
|
if (form.generateIframe.checked) {
|
||||||
// To properly escape all attributes, we are constructing an HTMLIframeElement
|
form.openButton.disabled = true
|
||||||
const iframe = document.createElement('iframe')
|
if (shareStringValue) {
|
||||||
iframe.setAttribute('src', shareStringValue)
|
// To properly escape all attributes, we are constructing an HTMLIframeElement
|
||||||
iframe.setAttribute('title', labelChatFor + ' ' + video.name)
|
const iframe = document.createElement('iframe')
|
||||||
iframe.setAttribute('sandbox', 'allow-same-origin allow-scripts allow-popups allow-forms')
|
iframe.setAttribute('src', shareStringValue)
|
||||||
iframe.setAttribute('width', '560')
|
iframe.setAttribute('title', labelChatFor + ' ' + video.name)
|
||||||
iframe.setAttribute('height', '315')
|
iframe.setAttribute('sandbox', 'allow-same-origin allow-scripts allow-popups allow-forms')
|
||||||
iframe.setAttribute('frameborder', '0')
|
iframe.setAttribute('width', '560')
|
||||||
shareStringValue = iframe.outerHTML
|
iframe.setAttribute('height', '315')
|
||||||
|
iframe.setAttribute('frameborder', '0')
|
||||||
|
shareStringValue = iframe.outerHTML
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
form.openButton.disabled = false
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
form.openButton.disabled = false
|
// we must generate a XMPP room address
|
||||||
|
// form.openButton.disabled = true
|
||||||
|
shareStringValue = getXMPPUri(registerOptions, settings, video)
|
||||||
}
|
}
|
||||||
form.shareString.setAttribute('value', shareStringValue ?? '')
|
form.shareString.setAttribute('value', shareStringValue ?? '')
|
||||||
}
|
}
|
||||||
@ -237,7 +308,8 @@ async function shareChatUrl (registerOptions: RegisterClientOptions, settings: a
|
|||||||
withscroll: !!form.withscroll.checked,
|
withscroll: !!form.withscroll.checked,
|
||||||
transparent: !!form.transparent.checked,
|
transparent: !!form.transparent.checked,
|
||||||
autocolors: !!form.autoColors?.checked,
|
autocolors: !!form.autoColors?.checked,
|
||||||
generateIframe: !!form.generateIframe.checked
|
generateIframe: !!form.generateIframe.checked,
|
||||||
|
protocol: !form.radioProtocolWeb || form.radioProtocolWeb.checked ? 'web' : 'xmpp'
|
||||||
}
|
}
|
||||||
window.localStorage.setItem('peertube-plugin-livechat-shareurl', JSON.stringify(v))
|
window.localStorage.setItem('peertube-plugin-livechat-shareurl', JSON.stringify(v))
|
||||||
}
|
}
|
||||||
@ -263,6 +335,11 @@ async function shareChatUrl (registerOptions: RegisterClientOptions, settings: a
|
|||||||
form.autoColors.checked = !!v.autocolors
|
form.autoColors.checked = !!v.autocolors
|
||||||
}
|
}
|
||||||
form.generateIframe.checked = !!v.generateIframe
|
form.generateIframe.checked = !!v.generateIframe
|
||||||
|
if (form.radioProtocolXMPP && v.protocol === 'xmpp') {
|
||||||
|
form.radioProtocolXMPP.checked = true
|
||||||
|
} else if (form.radioProtocolWeb) {
|
||||||
|
form.radioProtocolWeb.checked = true
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error(err as string)
|
logger.error(err as string)
|
||||||
}
|
}
|
||||||
|
@ -66,10 +66,31 @@ function getIframeUri (
|
|||||||
return iframeUriStr
|
return iframeUriStr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getXMPPUri (
|
||||||
|
registerOptions: RegisterClientOptions, settings: any, video: Video
|
||||||
|
): string | null {
|
||||||
|
// returns something like xmpp:256896ac-199a-4dab-bb3a-4fd916140272@room.instance.tdl?join
|
||||||
|
if (!settings['prosody-room-allow-s2s']) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
let uuid: string
|
||||||
|
if (settings['prosody-room-type'] === 'channel') {
|
||||||
|
uuid = 'channel.' + video.channel.id.toString()
|
||||||
|
} else {
|
||||||
|
uuid = video.uuid.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
const hostname = window.location.hostname
|
||||||
|
|
||||||
|
return 'xmpp:' + uuid + '@room.' + hostname + '?join'
|
||||||
|
}
|
||||||
|
|
||||||
export type {
|
export type {
|
||||||
UriOptions
|
UriOptions
|
||||||
}
|
}
|
||||||
export {
|
export {
|
||||||
getBaseRoute,
|
getBaseRoute,
|
||||||
getIframeUri
|
getIframeUri,
|
||||||
|
getXMPPUri
|
||||||
}
|
}
|
||||||
|
@ -21,5 +21,8 @@
|
|||||||
"Not found": false,
|
"Not found": false,
|
||||||
"Video": false,
|
"Video": false,
|
||||||
"Channel": false,
|
"Channel": false,
|
||||||
"Last activity": false
|
"Last activity": false,
|
||||||
|
"Web": false,
|
||||||
|
"Connect using XMPP": false,
|
||||||
|
"You can connect to the room using an external XMPP account, and your favorite XMPP client.": false
|
||||||
}
|
}
|
||||||
|
@ -21,5 +21,8 @@
|
|||||||
"Not found": false,
|
"Not found": false,
|
||||||
"Video": false,
|
"Video": false,
|
||||||
"Channel": false,
|
"Channel": false,
|
||||||
"Last activity": false
|
"Last activity": false,
|
||||||
|
"Web": false,
|
||||||
|
"Connect using XMPP": false,
|
||||||
|
"You can connect to the room using an external XMPP account, and your favorite XMPP client.": false
|
||||||
}
|
}
|
||||||
|
@ -21,5 +21,8 @@
|
|||||||
"Not found": false,
|
"Not found": false,
|
||||||
"Video": false,
|
"Video": false,
|
||||||
"Channel": false,
|
"Channel": false,
|
||||||
"Last activity": false
|
"Last activity": false,
|
||||||
|
"Web": false,
|
||||||
|
"Connect using XMPP": false,
|
||||||
|
"You can connect to the room using an external XMPP account, and your favorite XMPP client.": false
|
||||||
}
|
}
|
||||||
|
@ -21,5 +21,8 @@
|
|||||||
"Not found": false,
|
"Not found": false,
|
||||||
"Video": false,
|
"Video": false,
|
||||||
"Channel": false,
|
"Channel": false,
|
||||||
"Last activity": false
|
"Last activity": false,
|
||||||
|
"Web": false,
|
||||||
|
"Connect using XMPP": false,
|
||||||
|
"You can connect to the room using an external XMPP account, and your favorite XMPP client.": false
|
||||||
}
|
}
|
||||||
|
@ -21,5 +21,8 @@
|
|||||||
"Not found": false,
|
"Not found": false,
|
||||||
"Video": false,
|
"Video": false,
|
||||||
"Channel": false,
|
"Channel": false,
|
||||||
"Last activity": false
|
"Last activity": false,
|
||||||
|
"Web": false,
|
||||||
|
"Connect using XMPP": false,
|
||||||
|
"You can connect to the room using an external XMPP account, and your favorite XMPP client.": false
|
||||||
}
|
}
|
||||||
|
@ -21,5 +21,8 @@
|
|||||||
"Not found": "Non trouvé",
|
"Not found": "Non trouvé",
|
||||||
"Video": "Vidéo",
|
"Video": "Vidéo",
|
||||||
"Channel": "Chaîne",
|
"Channel": "Chaîne",
|
||||||
"Last activity": "Dernière activité"
|
"Last activity": "Dernière activité",
|
||||||
|
"Web": "Web",
|
||||||
|
"Connect using XMPP": "Connexion avec un client XMPP",
|
||||||
|
"You can connect to the room using an external XMPP account, and your favorite XMPP client.": "Vous pouvez vous connecter au salon en utilisant un compte XMPP externe, et votre client XMPP favori."
|
||||||
}
|
}
|
||||||
|
@ -21,5 +21,8 @@
|
|||||||
"Not found": "Non trovato",
|
"Not found": "Non trovato",
|
||||||
"Video": "Video",
|
"Video": "Video",
|
||||||
"Channel": "Canale",
|
"Channel": "Canale",
|
||||||
"Last activity": "Ultima attività"
|
"Last activity": "Ultima attività",
|
||||||
|
"Web": false,
|
||||||
|
"Connect using XMPP": false,
|
||||||
|
"You can connect to the room using an external XMPP account, and your favorite XMPP client.": false
|
||||||
}
|
}
|
||||||
|
@ -21,5 +21,8 @@
|
|||||||
"Not found": false,
|
"Not found": false,
|
||||||
"Video": false,
|
"Video": false,
|
||||||
"Channel": false,
|
"Channel": false,
|
||||||
"Last activity": false
|
"Last activity": false,
|
||||||
|
"Web": false,
|
||||||
|
"Connect using XMPP": false,
|
||||||
|
"You can connect to the room using an external XMPP account, and your favorite XMPP client.": false
|
||||||
}
|
}
|
||||||
|
@ -21,5 +21,8 @@
|
|||||||
"Not found": false,
|
"Not found": false,
|
||||||
"Video": false,
|
"Video": false,
|
||||||
"Channel": false,
|
"Channel": false,
|
||||||
"Last activity": false
|
"Last activity": false,
|
||||||
|
"Web": false,
|
||||||
|
"Connect using XMPP": false,
|
||||||
|
"You can connect to the room using an external XMPP account, and your favorite XMPP client.": false
|
||||||
}
|
}
|
||||||
|
@ -21,5 +21,8 @@
|
|||||||
"Not found": false,
|
"Not found": false,
|
||||||
"Video": false,
|
"Video": false,
|
||||||
"Channel": false,
|
"Channel": false,
|
||||||
"Last activity": false
|
"Last activity": false,
|
||||||
|
"Web": false,
|
||||||
|
"Connect using XMPP": false,
|
||||||
|
"You can connect to the room using an external XMPP account, and your favorite XMPP client.": false
|
||||||
}
|
}
|
||||||
|
@ -307,7 +307,7 @@ Please read
|
|||||||
label: loc('prosody_room_allow_s2s_label'),
|
label: loc('prosody_room_allow_s2s_label'),
|
||||||
type: 'input-checkbox',
|
type: 'input-checkbox',
|
||||||
default: false,
|
default: false,
|
||||||
private: true,
|
private: false,
|
||||||
descriptionHTML: loc('prosody_room_allow_s2s_description')
|
descriptionHTML: loc('prosody_room_allow_s2s_description')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user