chatComponent = { html: `
`, init: (el) => new Proxy({ scene: null, visible: true, visibleChatbar: false, messages: [], $videos: el.querySelector("#videos"), $messages: el.querySelector("#messages"), $chatline: el.querySelector("#chatline"), $chatbar: el.querySelector("#chatbar"), install(opts){ this.opts = opts this.scene = opts.scene el.className = "xrf" el.style.display = 'none' // start hidden document.body.appendChild( el ) this.visibleChatbar = false document.dispatchEvent( new CustomEvent("$chat:ready", {detail: opts}) ) this.send({message:`Welcome to ${document.location.search.substr(1)}, a 3D scene(file) which simply links to other ones.
You can start a solo offline exploration in XR right away.
Type /help below, or use the arrow- or WASD-keys on your keyboard, and mouse-drag to rotate.
`, class: ["info","guide","multiline"] }) }, initListeners(){ let {$chatline} = this $chatline.addEventListener('keydown', (e) => { if (e.key == 'Enter' ){ if( $chatline.value[0] != '/' ){ document.dispatchEvent( new CustomEvent("network.send", {detail: {message:$chatline.value}} ) ) } this.send({message: $chatline.value }) $chatline.value = '' if( window.innerHeight < 600 ) $chatline.blur() } }) console.dir(this.scene) }, toggle(){ this.visible = !this.visible if( this.visible && window.meeting.status == 'offline' ) window.meeting.start(this.opts) }, send(opts){ let {$messages} = this opts = { linebreak:true, message:"", class:[], ...opts } if( window.frontend && window.frontend.emit ) window.frontend.emit('$chat.send', opts ) let div = document.createElement('div') let msg = document.createElement('div') let br = document.createElement('br') let nick = document.createElement('div') msg.className = "msg" let html = `${ opts.message || ''}${ opts.html ? opts.html(opts) : ''}` if( $messages.last == html ) return msg.innerHTML = html if( opts.el ) msg.appendChild(opts.el) opts.id = Math.random() if( opts.class ){ msg.classList.add.apply(msg.classList, opts.class) br.classList.add.apply(br.classList, opts.class) div.classList.add.apply(div.classList, opts.class.concat(["envelope"])) } if( !opts.from && !msg.className.match(/(info|guide)/) ) msg.classList.add('self') if( opts.from ){ nick.className = "user" nick.innerText = opts.from+' ' div.appendChild(nick) if( opts.pos ){ let a = document.createElement("a") a.href = a.innerText = `#pos=${opts.pos}` nick.appendChild(a) } } div.appendChild(msg) $messages.appendChild(div) if( opts.linebreak ) div.appendChild(br) $messages.scrollTop = $messages.scrollHeight // scroll down $messages.last = msg.innerHTML }, getChatLog(){ return ([...this.$messages.querySelectorAll('.envelope')]) .filter( (d) => !d.className.match(/(info|ui)/) ) .map( (d) => d.innerHTML ) .join('\n') } },{ get(me,k,v){ return me[k] }, set(me,k,v){ me[k] = v switch( k ){ case "visible": { el.style.display = me.visible ? 'block' : 'none' if( !el.inited && (el.inited = true) ) me.initListeners() break; } case "visibleChatbar": { me.$chatbar.style.display = v ? 'block' : 'none' } } } }) } // reactify component! document.addEventListener('$menu:ready', (opts) => { opts = opts.detail document.head.innerHTML += chatComponent.css window.$chat = document.createElement('div') $chat.innerHTML = chatComponent.html $chat = chatComponent.init($chat) $chat.install(opts) //$menu.buttons = ([`📜 toggle text
`]) // .concat($menu.buttons) }) // alpine component for displaying meetings chatComponent.css = ` `