matrix now connects [crdt disabled]

This commit is contained in:
Leon van Kammen 2024-01-10 22:01:21 +01:00
parent a40d08d8de
commit a170aabfb6
10 changed files with 296 additions and 119 deletions

View file

@ -64,10 +64,11 @@
`,{timeout:false})
})
</script>
<script src="./../../../dist/aframe-blink-controls.min.js"></script> <!-- teleporting using controllers -->
<script src="./../../../dist/xrfragment.plugin.frontend.js"></script> <!-- menu + chat interface -->
<script src="./../../../dist/aframe-blink-controls.min.js"></script> <!-- teleporting using controllers -->
<script src="https://cdn.jsdelivr.net/npm/handy-work@3.1.9/build/handy-controls.min.js"></script> <!-- hand controllers -->
<script src="./../../../dist/xrfragment.plugin.p2p.js"></script> <!-- serverless p2p connectivity -->
<script src="./../../../dist/xrfragment.plugin.matrix.js"></script> <!-- matrix connectivity -->
<script src="./../../../dist/xrfragment.plugin.frontend.js"></script> <!-- menu + chat interface -->
</body>
</html>

View file

@ -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})")
}
})

View file

@ -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.<br>Protocols like [Matrix] allow you to view the full transcript<br>in a dedicated client like <a href='https://element.io' target='_blank'>element.io</a>")
}
},
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{

View file

@ -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 = `<option>${data[k].map((p)=>p.plugin.name).join('</option><option>')}</option>`; break;
case "chatnetwork": $chatnetwork.innerHTML = `<option>${data[k].map((p)=>p.plugin.name).join('</option><option>')}</option>`; break;
case "scene": $scene.innerHTML = `<option>${data[k].map((p)=>p.plugin.name).join('</option><option>')}</option>`; break;
case "webcam": $webcam.innerHTML = `<option>${data[k].map((p)=>p.profile.name).join('</option><option>')}</option>`; break;
case "chatnetwork": $chatnetwork.innerHTML = `<option>${data[k].map((p)=>p.profile.name).join('</option><option>')}</option>`; break;
case "scene": $scene.innerHTML = `<option>${data[k].map((p)=>p.profile.name).join('</option><option>')}</option>`; 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;}
</style>`

View file

@ -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
})
},

View file

@ -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: "";

View file

@ -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 ){

View file

@ -4,6 +4,7 @@ window.network = (opts) => new Proxy({
connected: false,
pos: '',
posName: '',
meetinglink: "",
peers: {},
plugin: {},

View file

@ -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) => `<div>
<div target="_blank" class="badge ruler">matrix <a onclick="frontend.plugin.matrix.info()"><i class="gg-info right"></i></a></div>
@ -60,7 +68,6 @@ window.matrix = (opts) => new Proxy({
</td>
</tr>
</table>
<small style="display:inline-block;float:right">Support for Oauth / OpenID is <a href="https://matrix.org/blog/#openid-connect" target="_blank">in progress</a></small>
<br>
</div>
`
@ -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(`<a href="${href}">#${network.posName}</a>`)
}
if( network.pos ){
pos.push(`<a href="${href}">#${`pos=${network.pos}`}</a>`)
}
if( pos.length ) message += `<br>📍 ${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.<br>Read more about it <a href="${this.plugin.url}" target="_blank">here</a>.<br>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.<br>Read more about it <a href="${this.profile.url}" target="_blank">here</a>.<br>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)

View file

@ -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) => `<div>
<div target="_blank" class="badge ruler">Peer2Peer WebRTC<a onclick="frontend.plugin.trystero.info()"><i class="gg-info right"></i></a></div>
<div target="_blank" class="badge ruler">Peer2Peer<a onclick="frontend.plugin.trystero.info()"><i class="gg-info right"></i></a></div>
<table>
<tr>
<td>nickname</td>
@ -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 <a onclick="$menu.share()">by clicking here</a>`,class:['info']})
$chat.send({message:"waiting for other humans..",class:['info']})
$chat.send({message:`Share the meeting link <a onclick="frontend.share()">by clicking here</a>`,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} <br>by using a serverless technology called <a href="https://webrtc.org/" target="_blank">webRTC</a> via <a href="${this.plugin.url}" target="_blank">trystero</a>.<br>You can basically make up your own channelname or choose an existing one.<br>Use this for hasslefree anonymous meetings.`)
window.notify(`${this.profile.name} is ${this.profile.description} <br>by using a serverless technology called <a href="https://webrtc.org/" target="_blank">webRTC</a> via <a href="${this.profile.url}" target="_blank">trystero</a>.<br>You can basically make up your own channelname or choose an existing one.<br>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