import { logger } from './logger' ; import { getIframeUri , UriOptions } from './uri' ; import { isAutoColorsAvailable } from 'shared/lib/autocolors' ; interface ShareForm { readonly : HTMLInputElement ; withscroll : HTMLInputElement ; withscrollLabelEl : HTMLElement ; url : HTMLInputElement ; autoColors ? : HTMLInputElement ; } async function shareChatUrl ( registerOptions , settings , video ) { const peertubeHelpers = registerOptions . peertubeHelpers ; const [ labelShare , labelReadonly , labelWithscroll , tipsOBS , labelCopy , labelCopied , labelError , labelOpen , labelAutocolors ] = await Promise . all ( [ peertubeHelpers . translate ( 'Share chat link' ) , peertubeHelpers . translate ( 'Read-only' ) , peertubeHelpers . translate ( 'Show the scrollbar' ) , peertubeHelpers . translate ( 'Tips for streamers: To add the chat to your OBS, generate a read-only link and use it as a browser source.' ) , peertubeHelpers . translate ( 'Copy' ) , peertubeHelpers . translate ( 'Link copied' ) , peertubeHelpers . translate ( 'Error' ) , peertubeHelpers . translate ( 'Open' ) , peertubeHelpers . translate ( 'Use current theme colors' ) ] ) ; const defaultUri = getIframeUri ( registerOptions , settings , video ) ; if ( ! defaultUri ) { return ; } let form ; function renderContent ( container ) { if ( ! form ) { container . childNodes . forEach ( child => container . removeChild ( child ) ) ; container . classList . add ( 'peertube-plugin-livechat-shareurl-modal' ) ; const divUrl = document . createElement ( 'div' ) ; divUrl . classList . add ( 'livechat-shareurl-copy' ) ; const url = document . createElement ( 'input' ) ; url . setAttribute ( 'type' , 'text' ) ; url . setAttribute ( 'readonly' , '' ) ; url . setAttribute ( 'autocomplete' , 'off' ) ; url . setAttribute ( 'placeholder' , '' ) ; url . classList . add ( 'form-control' , 'readonly' ) ; divUrl . append ( url ) ; const copy = document . createElement ( 'button' ) ; copy . classList . add ( 'btn' , 'btn-outline-secondary' , 'text-uppercase' ) ; copy . textContent = labelCopy ; divUrl . append ( copy ) ; const open = document . createElement ( 'button' ) ; open . classList . add ( 'btn' , 'btn-outline-secondary' , 'text-uppercase' ) ; open . textContent = labelOpen ; divUrl . append ( open ) ; container . append ( divUrl ) ; const divTips = document . createElement ( 'div' ) ; divTips . textContent = tipsOBS ; container . append ( divTips ) ; const divCustom = document . createElement ( 'div' ) ; divCustom . classList . add ( 'livechat-shareurl-custom' ) ; container . append ( divCustom ) ; const divReadonly = document . createElement ( 'div' ) ; divReadonly . classList . add ( 'livechat-shareurl-custom-readonly' ) ; divCustom . append ( divReadonly ) ; const readonly = document . createElement ( 'input' ) ; readonly . setAttribute ( 'type' , 'checkbox' ) ; const readonlyLabelEl = document . createElement ( 'label' ) ; readonlyLabelEl . textContent = labelReadonly ; readonlyLabelEl . prepend ( readonly ) ; divReadonly . append ( readonlyLabelEl ) ; const withscroll = document . createElement ( 'input' ) ; withscroll . setAttribute ( 'type' , 'checkbox' ) ; const withscrollLabelEl = document . createElement ( 'label' ) ; withscrollLabelEl . textContent = labelWithscroll ; withscrollLabelEl . prepend ( withscroll ) ; divReadonly . append ( withscrollLabelEl ) ; let autoColors ; if ( isAutoColorsAvailable ( settings [ 'chat-type' ] , settings [ 'converse-theme' ] ) ) { const label = document . createElement ( 'label' ) ; label . innerText = labelAutocolors ; autoColors = document . createElement ( 'input' ) ; autoColors . setAttribute ( 'type' , 'checkbox' ) ; label . prepend ( autoColors ) ; divCustom . append ( label ) ; } readonly . onclick = ( ) => { renderContent ( container ) ; } ; withscroll . onclick = ( ) => { renderContent ( container ) ; } ; if ( autoColors ) { autoColors . onclick = ( ) => { renderContent ( container ) ; } ; } url . onclick = ( ) => { url . select ( ) ; url . setSelectionRange ( 0 , 99999 ) ; } ; copy . onclick = ( ) => { url . select ( ) ; url . setSelectionRange ( 0 , 99999 ) ; navigator . clipboard . writeText ( url . value ) . then ( ( ) => { peertubeHelpers . notifier . success ( labelCopied ) ; } , ( ) => { peertubeHelpers . notifier . error ( labelError ) ; } ) ; } ; open . onclick = ( ) => { window . open ( url . value ) ; } ; form = { readonly , withscroll , withscrollLabelEl , url , autoColors } ; restore ( form ) ; } save ( form ) ; const uriOptions = { ignoreAutoColors : form . autoColors ? ! form . autoColors . checked : true , permanent : true } ; if ( form . readonly . checked ) { if ( form . withscroll . checked ) { uriOptions . readonly = true ; } else { uriOptions . readonly = 'noscroll' ; } form . withscrollLabelEl . style . display = 'initial' ; } else { form . withscrollLabelEl . style . display = 'none' ; } const iframeUri = getIframeUri ( registerOptions , settings , video , uriOptions ) ; form . url . setAttribute ( 'value' , iframeUri ?? '' ) ; } function save ( form ) { if ( ! window . localStorage ) { return ; } const v = { version : 1 , readonly : ! ! form . readonly . checked , withscroll : ! ! form . withscroll . checked , autocolors : ! ! form . autoColors ?. checked } ; window . localStorage . setItem ( 'peertube-plugin-livechat-shareurl' , JSON . stringify ( v ) ) ; } function restore ( form ) { if ( ! window . localStorage ) { return ; } const s = window . localStorage . getItem ( 'peertube-plugin-livechat-shareurl' ) ; if ( ! s ) { return ; } let v ; try { v = JSON . parse ( s ) ; if ( ! v || ( typeof v !== 'object' ) || v . version !== 1 ) { return ; } form . readonly . checked = ! ! v . readonly ; form . withscroll . checked = ! ! v . withscroll ; if ( form . autoColors ) { form . autoColors . checked = ! ! v . autocolors ; } } catch ( err ) { logger . error ( err as string ) ; } } logger . info ( 'Opening the share modal...' ) ; const observer = new MutationObserver ( mutations => { for ( const { addedNodes } of mutations ) { addedNodes . forEach ( node => { if ( ( node as HTMLElement ) . localName === 'ngb-modal-window' ) { logger . info ( 'Detecting a new modal, checking if this is the good one...' ) ; if ( ! ( node as HTMLElement ) . querySelector ) { return ; } const title = ( node as HTMLElement ) . querySelector ( '.modal-title' ) ; if ( ! ( title ?. textContent === labelShare ) ) { return ; } logger . info ( 'Yes, it is the good modal!' ) ; observer . disconnect ( ) ; const modalBodyElem = ( node as HTMLElement ) . querySelector ( '.modal-body' ) ; if ( ! modalBodyElem ) { logger . error ( 'Modal has no body... Dont know how to fill it.' ) ; return ; } renderContent ( modalBodyElem ) ; } } ) ; } } ) ; observer . observe ( document . body , { childList : true } ) ; peertubeHelpers . showModal ( { title : labelShare , content : `<p>${ defaultUri ?? '' }</p>` , close : true } ) ; setTimeout ( ( ) => { observer . disconnect ( ) ; } , 1000 ) ; } export { shareChatUrl } ;