matrix now connects [crdt disabled]
This commit is contained in:
parent
a40d08d8de
commit
a170aabfb6
10 changed files with 296 additions and 119 deletions
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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})")
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -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{
|
||||
|
|
|
|||
|
|
@ -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>`
|
||||
|
|
|
|||
|
|
@ -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
|
||||
})
|
||||
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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: "";
|
||||
|
|
|
|||
|
|
@ -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 ){
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ window.network = (opts) => new Proxy({
|
|||
|
||||
connected: false,
|
||||
pos: '',
|
||||
posName: '',
|
||||
meetinglink: "",
|
||||
peers: {},
|
||||
plugin: {},
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue