From a170aabfb686f342aedb8110dee98d3d297c692f Mon Sep 17 00:00:00 2001 From: Leon van Kammen Date: Wed, 10 Jan 2024 22:01:21 +0100 Subject: [PATCH] matrix now connects [crdt disabled] --- example/aframe/sandbox/index.html | 5 +- src/3rd/js/aframe/index.js | 4 +- src/3rd/js/plugin/frontend/$chat.js | 65 ++++++-- src/3rd/js/plugin/frontend/$connections.js | 69 ++++---- src/3rd/js/plugin/frontend/accessibility.js | 9 +- src/3rd/js/plugin/frontend/css.js | 6 +- src/3rd/js/plugin/frontend/frontend.js | 40 ++++- src/3rd/js/plugin/frontend/network.js | 1 + src/3rd/js/plugin/matrix/matrix.js | 176 +++++++++++++++----- src/3rd/js/plugin/p2p/trystero.js | 40 ++--- 10 files changed, 296 insertions(+), 119 deletions(-) diff --git a/example/aframe/sandbox/index.html b/example/aframe/sandbox/index.html index f4b7f5e..6ca6149 100644 --- a/example/aframe/sandbox/index.html +++ b/example/aframe/sandbox/index.html @@ -64,10 +64,11 @@ `,{timeout:false}) }) - - + + + diff --git a/src/3rd/js/aframe/index.js b/src/3rd/js/aframe/index.js index a3a346b..7588903 100644 --- a/src/3rd/js/aframe/index.js +++ b/src/3rd/js/aframe/index.js @@ -52,7 +52,9 @@ window.AFRAME.registerComponent('xrf', { el.setAttribute("class","floor") $('a-scene').appendChild(el) }) - blinkControls.components['blink-controls'].update({collisionEntities:true}) + let com = blinkControls.components['blink-controls'] + if( com ) com.update({collisionEntities:true}) + else console.warn("xrfragments: blink-controls is not mounted, please run manually: $('[blink-controls]).components['blink-controls'].update({collisionEntities:true})") } }) diff --git a/src/3rd/js/plugin/frontend/$chat.js b/src/3rd/js/plugin/frontend/$chat.js index a541ea6..31cf58c 100644 --- a/src/3rd/js/plugin/frontend/$chat.js +++ b/src/3rd/js/plugin/frontend/$chat.js @@ -19,6 +19,8 @@ chatComponent = { visibleChatbar: false, messages: [], + username: '', // configured by 'network.connected' event + $videos: el.querySelector("#videos"), $messages: el.querySelector("#messages"), $chatline: el.querySelector("#chatline"), @@ -37,6 +39,8 @@ chatComponent = { initListeners(){ let {$chatline} = this + + $chatline.addEventListener('click', (e) => this.inform() ) $chatline.addEventListener('keydown', (e) => { if (e.key == 'Enter' ){ if( $chatline.value[0] != '/' ){ @@ -47,14 +51,34 @@ chatComponent = { if( window.innerHeight < 600 ) $chatline.blur() } }) + + document.addEventListener('network.connected', (e) => { + if( e.detail.username ) this.username = e.detail.username + }) + console.dir(this.scene) }, + inform(){ + if( !this.inform.informed && (this.inform.informed = true) ){ + window.notify("Here you can update your statusline.
Protocols like [Matrix] allow you to view the full transcript
in a dedicated client like element.io") + } + }, + toggle(){ this.visible = !this.visible if( this.visible && window.meeting.status == 'offline' ) window.meeting.start(this.opts) }, + hyphenate(str){ + return String(str).replace(/[^a-zA-Z0-9]/g,'-') + }, + + // sending messages to the #messages div + // every user can post maximum one msg at a time + // it's more like a 'status' which is more friendly + // for accessibility reasons + // for a fullfledged chat/transcript see matrix clients send(opts){ let {$messages} = this opts = { linebreak:true, message:"", class:[], ...opts } @@ -74,7 +98,12 @@ chatComponent = { 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 && !msg.className.match(/(info|guide)/) ){ + let frag = xrf.URI.parse(document.location.hash) + opts.from = this.username + if( frag.pos ) opts.pos = frag.pos.string + msg.classList.add('self') + } if( opts.from ){ nick.className = "user" nick.innerText = opts.from+' ' @@ -86,6 +115,15 @@ chatComponent = { } } div.appendChild(msg) + // force one message per user + if( opts.from ){ + div.id = this.hyphenate(opts.from) + let oldMsg = $messages.querySelector(`#${div.id}`) + if( oldMsg ) oldMsg.remove() + } + // remove after timeout + if( opts.timeout ) setTimeout( (div) => div.remove(), opts.timeout, div ) + // finally add the message on top $messages.appendChild(div) if( opts.linebreak ) div.appendChild(br) $messages.scrollTop = $messages.scrollHeight // scroll down @@ -196,12 +234,15 @@ chatComponent.css = ` max-width:unset; } #messages{ + display: flex; + flex-direction: column-reverse; + align-items: flex-start; position: absolute; transition:1s; top: 0px; left: 0; - bottom: 130px; - padding: 15px; + bottom: 49px; + padding: 20px; overflow:hidden; pointer-events:none; transition:1s; @@ -217,9 +258,7 @@ chatComponent.css = ` top:50px; } #messages:hover { - background: #FFF5; pointer-events:all; - overflow-y: auto; } #messages *{ pointer-events:all; @@ -229,7 +268,7 @@ chatComponent.css = ` background: #fff; display: inline-block; padding: 1px 17px; - border-radius: 20px 0px 20px 20px; + border-radius: 20px; color: #000c; margin-bottom: 10px; line-height:23px; @@ -239,8 +278,8 @@ chatComponent.css = ` border: 1px solid #0002; } #messages .msg.self{ - border-radius: 0px 20px 20px 20px; - background:var(--xrf-primary); + border-radius: 20px; + background:var(--xrf-box-shadow); } #messages .msg.self, #messages .msg.self div{ @@ -259,12 +298,16 @@ chatComponent.css = ` } #messages .msg a { text-decoration:underline; - color: #EEE; + color: var(--xrf-primary); font-weight:bold; - transition:1s; + transition:0.3s; + } + #messages .msg.info a, + #messages .ruler a{ + color:#FFF; } #messages .msg a:hover{ - color:#FFF; + color:#000; } #messages .msg.ui, #messages .msg.ui div{ diff --git a/src/3rd/js/plugin/frontend/$connections.js b/src/3rd/js/plugin/frontend/$connections.js index 31d4681..8a1fc2d 100644 --- a/src/3rd/js/plugin/frontend/$connections.js +++ b/src/3rd/js/plugin/frontend/$connections.js @@ -82,9 +82,9 @@ connectionsComponent = { init: (el) => new Proxy({ - webcam: [{plugin:{name:"No thanks"},config: () => document.createElement('div')}], - chatnetwork: [{plugin:{name:"No thanks"},config: () => document.createElement('div')}], - scene: [{plugin:{name:"No thanks"},config: () => document.createElement('div')}], + webcam: [{profile:{name:"No thanks"},config: () => document.createElement('div')}], + chatnetwork: [{profile:{name:"No thanks"},config: () => document.createElement('div')}], + scene: [{profile:{name:"No thanks"},config: () => document.createElement('div')}], selectedWebcam: '', selectedChatnetwork:'', @@ -126,21 +126,27 @@ connectionsComponent = { } }, - show(){ - $chat.visible = true - // hide networking settings if entering thru meetinglink - $networking.style.display = document.location.href.match(/meet=/) ? 'none' : 'block' - if( !network.connected ){ - if( el.parentElement ) el.parentElement.parentElement.remove() - $chat.send({message:"", el, class:['ui']}) - if( !network.meetinglink ){ // set default - $webcam.value = 'Peer2Peer' - $chatnetwork.value = 'Peer2Peer' - $scene.value = 'Peer2Peer' - } - this.renderSettings() + show(opts){ + opts = opts || {} + if( opts.hide ){ + el.parentElement.parentElement.style.display = 'none' }else{ - $chat.send({message:"you are already connected, refresh page to create new connection",class:['info']}) + $chat.visible = true + // hide networking settings if entering thru meetinglink + $networking.style.display = document.location.href.match(/meet=/) ? 'none' : 'block' + if( !network.connected ){ + if( el.parentElement ) el.parentElement.parentElement.remove() + document.querySelector('body > .xrf').appendChild(el) + $chat.send({message:"", el, class:['ui']}) + if( !network.meetinglink ){ // set default + $webcam.value = 'Peer2Peer' + $chatnetwork.value = 'Peer2Peer' + $scene.value = 'Peer2Peer' + } + this.renderSettings() + }else{ + $chat.send({message:"you are already connected, refresh page to create new connection",class:['info']}) + } } }, @@ -153,7 +159,7 @@ connectionsComponent = { forSelectedPluginsDo(cb){ // this function looks weird but it's handy to prevent the same plugins rendering duplicate configurations let plugins = {} - let select = (name) => (o) => o.plugin.name == name ? plugins[ o.plugin.name ] = o : '' + let select = (name) => (o) => o.profile.name == name ? plugins[ o.profile.name ] = o : '' this.webcam.find( select(this.selectedWebcam) ) this.chatnetwork.find( select(this.selectedChatnetwork) ) this.scene.find( select(this.selectedScene) ) @@ -223,25 +229,18 @@ connectionsComponent = { }) }, - reactToNetwork(){ - document.addEventListener('network.connected', () => { - console.log("network.connected") - window.notify("🪐 connected to awesomeness..") - $chat.visibleChatbar = true - $chat.send({message:`🎉 connected!`,class:['info']}) - }) + reactToNetwork(){ // *TODO* move to network? + document.addEventListener('network.connect', () => { - console.log("network.connect") - el.parentElement.classList.add('connecthide') - window.notify("🪐 connecting to awesomeness..") - $connect.innerText = 'connecting..' + this.show({hide:true}) + $connect.innerText = 'connecting..' }) + document.addEventListener('network.disconnect', () => { - window.notify("🪐 disconnecting..") $connect.innerText = 'disconnecting..' setTimeout( () => $connect.innerText = 'connect', 1000) - if( !window.accessibility.enabled ) $chat.visibleChatbar = false }) + } },{ @@ -250,9 +249,9 @@ connectionsComponent = { set(data,k,v){ data[k] = v switch( k ){ - case "webcam": $webcam.innerHTML = ``; break; - case "chatnetwork": $chatnetwork.innerHTML = ``; break; - case "scene": $scene.innerHTML = ``; break; + case "webcam": $webcam.innerHTML = ``; break; + case "chatnetwork": $chatnetwork.innerHTML = ``; break; + case "scene": $scene.innerHTML = ``; break; case "selectedScene": $scene.value = v; data.renderSettings(); break; case "selectedChatnetwork": $chatnetwork.value = v; data.renderSettings(); break; case "selectedWebcam": { @@ -297,7 +296,7 @@ connectionsComponent.css = ` display: block; position: relative; float: right; - margin-bottom: 7px; + top: 16px; } #messages .msg.ui div.tab-frame > div.tab{ padding:25px 10px 5px 10px;} ` diff --git a/src/3rd/js/plugin/frontend/accessibility.js b/src/3rd/js/plugin/frontend/accessibility.js index 9f5757e..28ad7ea 100644 --- a/src/3rd/js/plugin/frontend/accessibility.js +++ b/src/3rd/js/plugin/frontend/accessibility.js @@ -83,16 +83,19 @@ window.accessibility = (opts) => new Proxy({ document.addEventListener('network.send', (e) => { let opts = e.detail opts.message = opts.message || '' - if( opts.class && ~opts.class.indexOf('info') ) opts.message = `info: ${opts.message}` this.speak(opts.message) }) opts.xrf.addEventListener('pos', (opts) => { if( this.enabled ){ $chat.send({message: this.posToMessage(opts) }) + network.send({message: this.posToMessage(opts), class:["info","guide"]}) + } + if( opts.frag.pos.string.match(/,/) ){ + network.pos = opts.frag.pos.string + }else{ + network.posName = opts.frag.pos.string } - network.send({message: this.posToMessage(opts), class:["info","guide"]}) - network.pos = opts.frag.pos.string }) }, diff --git a/src/3rd/js/plugin/frontend/css.js b/src/3rd/js/plugin/frontend/css.js index a2300a7..c1522f4 100644 --- a/src/3rd/js/plugin/frontend/css.js +++ b/src/3rd/js/plugin/frontend/css.js @@ -535,7 +535,7 @@ document.head.innerHTML += ` position: relative; display: inline-block; -moz-transform: rotate(-45deg) scale(var(--ggs,1)); - transform: translate(4px,-5px) rotate(-45deg) scale(var(--ggs,1)); + transform: translate(4px,1px) rotate(-45deg) scale(var(--ggs,1)); width: 8px; height: 2px; background: currentColor; @@ -701,14 +701,14 @@ document.head.innerHTML += ` box-sizing: border-box; position: relative; display: inline-block; - transform: scale(var(--ggs,1)) translate(3px,2px); + transform: scale(var(--ggs,1)) translate(3px,9px); width: 16px; height: 6px; border: 2px solid; border-top: 0; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; - margin-top: 8px + line-height:15px; } .gg-software-download::after { content: ""; diff --git a/src/3rd/js/plugin/frontend/frontend.js b/src/3rd/js/plugin/frontend/frontend.js index e2f34f4..01715eb 100644 --- a/src/3rd/js/plugin/frontend/frontend.js +++ b/src/3rd/js/plugin/frontend/frontend.js @@ -41,6 +41,7 @@ window.frontend = (opts) => new Proxy({ .setupIframeUrlHandler() .setupCapture() .setupUserHints() + .setupNetworkListeners() .hidetopbarWhenMenuCollapse() window.notify = this.notify @@ -92,6 +93,37 @@ window.frontend = (opts) => new Proxy({ return this }, + setupNetworkListeners(){ + + document.addEventListener('network.connect', (e) => { + console.log("network.connect") + window.notify("🪐 connecting to awesomeness..") + $chat.send({message:`🪐 connecting to awesomeness..`,class:['info'], timeout:5000}) + }) + + document.addEventListener('network.connected', (e) => { + window.notify("🪐 connected to awesomeness..") + $chat.visibleChatbar = true + $chat.send({message:`🎉 ${e.detail.plugin.profile.name||''} connected!`,class:['info'], timeout:5000}) + }) + + document.addEventListener('network.disconnect', () => { + window.notify("🪐 disconnecting..") + }) + + document.addEventListener('network.info', (e) => { + window.notify(e.detail.message) + $chat.send({...e.detail, class:['info'], timeout:5000}) + }) + + document.addEventListener('network.error', (e) => { + window.notify(e.detail.message) + $chat.send({...e.detail, class:['info'], timeout:5000}) + }) + + return this + }, + hidetopbarWhenMenuCollapse(){ // hide topbar when menu collapse button is pressed document.addEventListener('$menu:collapse', (e) => this.el.querySelector("#topbar").style.display = e.detail === true ? 'block' : 'none') @@ -185,12 +217,14 @@ window.frontend = (opts) => new Proxy({ }, share(opts){ - opts = opts || {notify:true,qr:true,share:true} + opts = opts || {notify:true,qr:true,share:true,linkonly:false} if( network.connected && !document.location.hash.match(/meet=/) ){ - let p = $connections.chatnetwork.find( (p) => p.plugin.name == $connections.selectedChatnetwork ) - if( p.link ) document.location.hash += `&meet=${p.link}` + let p = $connections.chatnetwork.find( (p) => p.profile.name == $connections.selectedChatnetwork ) + console.dir(p) + if( p.link ) document.location.hash = `${ network.pos ? `pos=${network.pos}` : ''}&meet=${p.link}` } let url = window.location.href + if( opts.linkonly ) return url this.copyToClipboard( url ) // End of *TODO* if( opts.notify ){ diff --git a/src/3rd/js/plugin/frontend/network.js b/src/3rd/js/plugin/frontend/network.js index 1dc3f4f..90c0892 100644 --- a/src/3rd/js/plugin/frontend/network.js +++ b/src/3rd/js/plugin/frontend/network.js @@ -4,6 +4,7 @@ window.network = (opts) => new Proxy({ connected: false, pos: '', + posName: '', meetinglink: "", peers: {}, plugin: {}, diff --git a/src/3rd/js/plugin/matrix/matrix.js b/src/3rd/js/plugin/matrix/matrix.js index 0381151..4a74d16 100644 --- a/src/3rd/js/plugin/matrix/matrix.js +++ b/src/3rd/js/plugin/matrix/matrix.js @@ -2,7 +2,7 @@ window.matrix = (opts) => new Proxy({ el: null, // HTML element - plugin:{ + profile:{ type: 'network', name: '[Matrix]', description: 'a standardized decentralized privacy-friendly protocol', @@ -11,9 +11,13 @@ window.matrix = (opts) => new Proxy({ video: false, audio: false, chat: true, - scene: true + scene: false }, + useWebcam: false, + useChat: false, + useScene: false, + channel: '#xrfragment-test:matrix.org', server: 'https://matrix.org', username:'', @@ -22,6 +26,10 @@ window.matrix = (opts) => new Proxy({ client: null, roomid: '', + // Matrix-CRDT + ydoc: null, + yhref: null, + html: { generic: (opts) => `
matrix
@@ -60,7 +68,6 @@ window.matrix = (opts) => new Proxy({ - Support for Oauth / OpenID is in progress
` @@ -69,65 +76,139 @@ window.matrix = (opts) => new Proxy({ init(){ frontend.plugin['matrix'] = this $connections.chatnetwork = $connections.chatnetwork.concat([this]) - $connections.scene = $connections.scene.concat([this]) this.reactToConnectionHrefs() this.nickname = localStorage.getItem("nickname") || `human${String(Math.random()).substr(5,4)}` document.addEventListener('network.connect', (e) => this.connect(e.detail) ) document.addEventListener('network.init', () => { let meeting = network.getMeetingFromUrl(document.location.href) - if( meeting.match(this.plugin.protocol) ){ + if( meeting.match(this.profile.protocol) ){ this.parseLink( meeting ) } }) }, connect(opts){ - console.log("connecting "+this.plugin.name) - this.channel = document.querySelector("#matrix input#channel").value - this.server = document.querySelector("#matrix input#server").value - this.username = document.querySelector("#matrix input#username").value - this.auth = document.querySelector("#matrix select#auth").value - let secret = document.querySelector("#matrix input#secret").value - document.querySelector("#matrix input#secret").value = '' + if( opts.selectedWebcam == this.profile.name ) this.useWebcam = true + if( opts.selectedChatnetwork == this.profile.name ) this.useChat = true + if( opts.selectedScene == this.profile.name ) this.useScene = true + if( this.useWebcam || this.useScene || this.useChat ){ + this.link = `matrix://r/${this.channel.replace(/^#/,'')}` + console.log("connecting "+this.profile.name) + this.channel = document.querySelector("#matrix input#channel").value + this.server = document.querySelector("#matrix input#server").value + this.username = document.querySelector("#matrix input#username").value + this.auth = document.querySelector("#matrix select#auth").value + let secret = document.querySelector("#matrix input#secret").value + document.querySelector("#matrix input#secret").value = '' - let credentials = { baseUrl: this.server } + let credentials = { baseUrl: this.server } - if( this.auth == 'via access token'){ - credentials.accessToken = secret - credentials.userId = this.username + if( this.auth == 'via access token'){ + credentials.accessToken = secret + credentials.userId = this.username + } + this.client = Matrix.sdk.createClient(credentials) + // Extra configuration needed for certain matrix-js-sdk + // calls to work without calling sync start functions + this.client.canSupportVoip = false; + this.client.clientOpts = { + lazyLoadMembers: true, + }; + + // auth + if( this.auth == 'via password'){ + this.client.login("m.login.password",{"user": this.username, password: secret}) + .then( () => this.onMatrixConnect() ) + .catch( () => window.notify("authentication was not succesful 😞")) + }else this.onMatrixConnect() } - this.client = Matrix.sdk.createClient(credentials) - if( this.auth == 'via password'){ - this.client.login("m.login.password",{"user": this.username, password: secret}) - .then( () => this.onMatrixConnect() ) - .catch( () => window.notify("authentication was not succesful 😞")) - }else this.onMatrixConnect() }, onMatrixConnect(){ - // token: this.matrixclient.getAccessToken() - this.client.startClient() - client.once('sync', function(state, prevState, res) { - if( state == 'PREPARED' ) this.setupListeners() - else console.log("state: "+state) + // token: this.matrixclient.getAccessToken() + frontend.emit('network.info',{message:'🛰 syncing with Matrix (might take a while)',plugin:this}) + frontend.emit('network.connected',{plugin:this,username: this.username}) + this.client.startClient({ initialSyncLimit: 4 }) // show last 4 messages? + // get roomId of channel + this.client.getRoomIdForAlias(this.channel) + .then( (o) => { + this.roomId = o.room_id + this.setupListeners() + }) + .catch((e) => { + frontend.emit('network.error',{plugin:this,message:`channel ${this.channel} cannot be joined: `+String(e)}) + }) + }, + + setupCRDT(){ + // Create a new Y.Doc and connect the MatrixProvider + this.ydoc = new Matrix.Y.Doc(); + const provider = new Matrix.MatrixProvider(this.ydoc, this.client, { + type: "alias", + alias: this.channel }); + provider.initialize(); + + this.yhref = this.ydoc.getText('href') + // observe changes of the sum + this.yhref.observe((event) => { + console.log("new yhref: " + yhref.toString ); + }); + debugger + + }, + + getNormalizedName(){ + return this.channel.replace(/(^#|:.*)/,'') }, setupListeners(){ - let rooms = this.client.getRooms(); - rooms.forEach(room => { - console.log(room); - }); - this.client.on("Room.timeline", function(event, room, toStartOfTimeline) { - if( event.room_id && event.room_id == this.roomid ){ - console.dir(event); + if( this.useChat ) this.setupChat() + //if( this.useScene ) this.setupCRDT() /* throws weird errors, perhaps matrix-sdk-js is too new */ + return this + }, + + setupChat(){ + + // receive receivemessages + this.client.on("Room.timeline", (event, room, toStartOfTimeline) => { + if (event.getType() !== "m.room.message") return // only print messages + if( room.roomId == this.roomId ){ + $chat.send({message: event.getContent().body, from: event.getSender()}) } }); + + // send chatmessages + document.addEventListener('network.send', (e) => { + let {message} = e.detail + let href = frontend.share({linkonly:true}) // get our meetinglink in there + // convert to absolute links + if( message.match(/href="#/) ){ + message = message.replace(/href=['"]#.*?['"]/g, `href="${href}"`) + }else{ + let pos = [] + if( network.posName ){ + pos.push(`#${network.posName}`) + } + if( network.pos ){ + pos.push(`#${`pos=${network.pos}`}`) + } + if( pos.length ) message += `
📍 ${pos.join(' ')}` + } + let content = { + body: message, + format: "org.matrix.custom.html", + formatted_body: message, + msgtype:"m.text" + } + this.client.sendEvent( this.roomId, "m.room.message", content, "", (err,res) => console.error(err) ) + }) + }, config(opts){ - opts = {...opts, ...this.plugin } + opts = {...opts, ...this.profile } this.el = document.createElement('div') let html = this.html.generic(opts) for( let i in opts ){ @@ -141,18 +222,18 @@ window.matrix = (opts) => new Proxy({ }, info(opts){ - window.notify(`${this.plugin.name} is ${this.plugin.description}, it is the hottest internet technology available at this moment.
Read more about it here.
You can basically make up a new channelname or use an existing one`) + window.notify(`${this.profile.name} is ${this.profile.description}, it is the hottest internet technology available at this moment.
Read more about it here.
You can basically make up a new channelname or use an existing one`) }, parseLink(url){ - if( !url.match(this.plugin.protocol) ) return - let parts = url.replace(this.plugin.protocol,'').split("/") + if( !url.match(this.profile.protocol) ) return + let parts = url.replace(this.profile.protocol,'').split("/") if( parts[0] == 'r' ){ // room let server = parts.split("/")[1].replace(/:.*/,'') let channel = parts.split("/")[1].replace(/.*:/,'') $connections.show() - $connections.selectedChatnetwork = this.plugin.name - $connections.selectedScene = this.plugin.name + $connections.selectedChatnetwork = this.profile.name + $connections.selectedScene = this.profile.name this.el.querySelector('#channel').value = `#${channel}:${server}` this.el.querySelector('#server').value = server console.log("configured matrix") @@ -160,6 +241,15 @@ window.matrix = (opts) => new Proxy({ return false }, + t0nkr0nst0nreateLink(opts){ + let hash = document.location.hash + if( !this.link ){ + const meeting = network.getMeetingFromUrl(document.location.href) + this.link = meeting.match("matrix://") ? meeting : '' + } + if( !hash.match('meet=') ) document.location.hash += `${hash.length > 1 ? '&' : '#'}meet=${this.link}` + }, + reactToConnectionHrefs(){ xrf.addEventListener('href', (opts) => { let {mesh} = opts @@ -168,7 +258,11 @@ window.matrix = (opts) => new Proxy({ let href = mesh.userData.href let isLocal = href[0] == '#' let isTeleport = href.match(/(pos=|http:)/) - if( isLocal && !isTeleport && this.href.send ) this.href.send({href}) + console.log("href detected") + if( isLocal && !isTeleport && this.client && this.useScene ){ + console.log("sending href") + this.yhref.set( document.location.hash ) + } }) let hashvars = xrf.URI.parse( document.location.hash ) if( hashvars.meet ) this.parseLink(hashvars.meet.string) diff --git a/src/3rd/js/plugin/p2p/trystero.js b/src/3rd/js/plugin/p2p/trystero.js index 76c6db7..de692da 100644 --- a/src/3rd/js/plugin/p2p/trystero.js +++ b/src/3rd/js/plugin/p2p/trystero.js @@ -1,9 +1,9 @@ window.trystero = (opts) => new Proxy({ - plugin:{ + profile:{ type: 'network', name: 'Peer2Peer', - description: 'P2P using WebRTC over bittorrent for signaling & encryption', + description: 'WebRTC over bittorrent for signaling & encryption', url: 'https://github.com/dmotz/trystero', protocol: 'trystero://', video: true, @@ -14,7 +14,7 @@ window.trystero = (opts) => new Proxy({ html: { generic: (opts) => `
-
Peer2Peer WebRTC
+
Peer2Peer
@@ -62,7 +62,7 @@ window.trystero = (opts) => new Proxy({ document.addEventListener('network.connect', (e) => this.connect(e.detail) ) document.addEventListener('network.init', () => { let meeting = network.getMeetingFromUrl(document.location.href) - if( meeting.match(this.plugin.protocol) ){ + if( meeting.match(this.profile.protocol) ){ this.parseLink( meeting ) } }) @@ -71,25 +71,25 @@ window.trystero = (opts) => new Proxy({ confirmConnected(){ if( !this.connected ){ this.connected = true - frontend.emit('network.connected',{plugin:this}) + frontend.emit('network.connected',{plugin:this,username: this.nickname}) this.names[ this.selfId ] = this.nickname } }, async connect(opts){ // embedded https://github.com/dmotz/trystero (trystero-torrent.min.js build) - console.log("connecting "+this.plugin.name) this.createLink() // ensure link - if( opts.selectedWebcam == this.plugin.name ) this.useWebcam = true - if( opts.selectedChatnetwork == this.plugin.name ) this.useChat = true - if( opts.selectedScene == this.plugin.name ) this.useScene = true + if( opts.selectedWebcam == this.profile.name ) this.useWebcam = true + if( opts.selectedChatnetwork == this.profile.name ) this.useChat = true + if( opts.selectedScene == this.profile.name ) this.useScene = true if( this.useWebcam || this.useChat || this.useScene ){ + console.log("connecting "+this.profile.name) console.log("trystero link: "+this.link) this.room = joinRoom( {appId: 'xrfragment'}, this.link ) - $chat.send({message:`Share the meeting link by clicking here`,class:['info']}) - $chat.send({message:"waiting for other humans..",class:['info']}) + $chat.send({message:`Share the meeting link by clicking here`,class:['info'],timeout:10000}) + $chat.send({message:"waiting for other humans..",class:['info'], timeout:5000}) // setup trystero events const [sendPing, getPing] = this.room.makeAction('ping') @@ -121,7 +121,7 @@ window.trystero = (opts) => new Proxy({ if( this.useWebcam ) this.initWebcam() if( this.useChat ) this.initChat() - if( this.useScene ) this.initScene() + if( this.useScene ) this.initScene() } }, @@ -151,7 +151,7 @@ window.trystero = (opts) => new Proxy({ }, async initWebcam(){ - if( !$connections.$audioInput.value && !$connections.$videInput.value ) return // nothing to do + if( !$connections.$audioInput.value && !$connections.$videoInput.value ) return // nothing to do // get a local audio stream from the microphone this.selfStream = await navigator.mediaDevices.getUserMedia({ @@ -215,7 +215,7 @@ window.trystero = (opts) => new Proxy({ }, config(opts){ - opts = {...opts, ...this.plugin } + opts = {...opts, ...this.profile } this.el = document.createElement('div') this.el.innerHTML = this.html.generic(opts) this.el.querySelector('#nickname').value = this.nickname @@ -225,21 +225,21 @@ window.trystero = (opts) => new Proxy({ }, info(opts){ - window.notify(`${this.plugin.name} is ${this.plugin.description}
by using a serverless technology called webRTC via trystero.
You can basically make up your own channelname or choose an existing one.
Use this for hasslefree anonymous meetings.`) + window.notify(`${this.profile.name} is ${this.profile.description}
by using a serverless technology called webRTC via trystero.
You can basically make up your own channelname or choose an existing one.
Use this for hasslefree anonymous meetings.`) }, parseLink(url){ - if( !url.match(this.plugin.protocol) ) return - let parts = url.replace(this.plugin.protocol,'').split("/") + if( !url.match(this.profile.protocol) ) return + let parts = url.replace(this.profile.protocol,'').split("/") if( parts[0] == 'r' ){ // this.room let roomid = parts[1].replace(/:.*/,'') let server = parts[1].replace(/.*:/,'') if( server != 'bittorrent' ) return window.notify("only bittorrent is supported for trystero (for now) :/") this.link = url $connections.show() - $connections.selectedWebcam = this.plugin.name - $connections.selectedChatnetwork= this.plugin.name - $connections.selectedScene = this.plugin.name + $connections.selectedWebcam = this.profile.name + $connections.selectedChatnetwork= this.profile.name + $connections.selectedScene = this.profile.name return true } return false
nickname