work in progress [might break]
This commit is contained in:
parent
fceaf07c1f
commit
21ef1ded86
7 changed files with 220 additions and 84 deletions
|
|
@ -135,7 +135,8 @@ chatComponent.css = `
|
|||
button#showchat{
|
||||
z-index: 1500;
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
bottom: 24px;
|
||||
height: 34px;
|
||||
left: 20px;
|
||||
width: 48%;
|
||||
background: white;
|
||||
|
|
@ -158,6 +159,8 @@ chatComponent.css = `
|
|||
border:none;
|
||||
width:90%;
|
||||
box-sizing:border-box;
|
||||
height: 24px;
|
||||
font-size: var(--xrf-font-size-2);
|
||||
}
|
||||
#messages{
|
||||
position: absolute;
|
||||
|
|
@ -207,6 +210,9 @@ chatComponent.css = `
|
|||
#messages .msg.multiline {
|
||||
padding: 2px 14px;
|
||||
}
|
||||
#messages .msg.config {
|
||||
background:#
|
||||
}
|
||||
#messages button {
|
||||
text-decoration:none;
|
||||
margin: 0px 15px 10px 0px;
|
||||
|
|
@ -223,15 +229,6 @@ chatComponent.css = `
|
|||
#messages,#chatbar,#chatbar *, #messages *{
|
||||
}
|
||||
|
||||
#messages input{
|
||||
padding: 7px 15px;
|
||||
border-block: none;
|
||||
border-inline: none;
|
||||
border: 1px solid #888;
|
||||
background: var(--xrf-lighter-gray);
|
||||
height: 18px;
|
||||
max-width:168px;
|
||||
}
|
||||
|
||||
#messages button.emoticon,
|
||||
#messages .btn.emoticon {
|
||||
|
|
@ -253,7 +250,7 @@ chatComponent.css = `
|
|||
background:#EEE;
|
||||
}
|
||||
|
||||
nomargin{
|
||||
.nomargin{
|
||||
margin:0;
|
||||
}
|
||||
</style>`
|
||||
|
|
|
|||
|
|
@ -26,21 +26,25 @@ connectionsComponent = {
|
|||
<div id="settings"></div>
|
||||
<br>
|
||||
<button id="connect" onclick="$connections.connect()">📡 Connect!</button>
|
||||
<br>
|
||||
<br><br>
|
||||
</div>
|
||||
`,
|
||||
|
||||
init: (el) => new Proxy({
|
||||
|
||||
webcam: [{plugin:{name:"No thanks"},config(){}}],
|
||||
chatnetwork: [{plugin:{name:"No thanks"},config(){}}],
|
||||
scene: [{plugin:{name:"No thanks"},config(){}}],
|
||||
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')}],
|
||||
|
||||
selectedWebcam: '',
|
||||
selectedChatnetwork:'',
|
||||
selectedScene: '',
|
||||
|
||||
$webcam: $webcam = el.querySelector("#webcam"),
|
||||
$chatnetwork: $chatnetwork = el.querySelector("#chatnetwork"),
|
||||
$scene: $scene = el.querySelector("#scene"),
|
||||
$settings: $settings = el.querySelector("#settings"),
|
||||
|
||||
$connect: $connect = el.querySelector("#connect"),
|
||||
|
||||
install(opts){
|
||||
this.opts = opts
|
||||
|
|
@ -49,49 +53,62 @@ connectionsComponent = {
|
|||
$webcam.addEventListener('change', () => this.renderSettings() )
|
||||
$chatnetwork.addEventListener('change', () => this.renderSettings() )
|
||||
$scene.addEventListener('change', () => this.renderSettings() )
|
||||
|
||||
},
|
||||
|
||||
show(){
|
||||
$chat.visible = true
|
||||
if( !network.connected ){
|
||||
if( el.parentElement ) el.parentElement.remove()
|
||||
$chat.send({message:"", el})
|
||||
this.renderSettings()
|
||||
if( !network.meetinglink ){ // set default
|
||||
$webcam.value = 'Peer2Peer'
|
||||
$chatnetwork.value = 'Peer2Peer'
|
||||
$scene.value = 'Peer2Peer'
|
||||
}
|
||||
}else $chat.send({message:"you are already connected, refresh page to create new connection",class:['info']})
|
||||
},
|
||||
|
||||
connect(){
|
||||
navigator.share({
|
||||
url: 'https://foo.com',
|
||||
title: 'your meeting link'
|
||||
})
|
||||
this.update()
|
||||
this.webcam.selected.connect({webcam:true})
|
||||
this.chatnetwork.selected.connect({chat:true})
|
||||
this.scene.selected.connect({scene:true})
|
||||
this.$connect.setAttribute('disabled','disabled')
|
||||
this.$connect.classList.add('disabled')
|
||||
window.notify("🪐 connecting to awesomeness..")
|
||||
},
|
||||
|
||||
update(){
|
||||
this.selectedWebcam = $webcam.value
|
||||
this.selectedChatnetwork = $chatnetwork.value
|
||||
this.selectedScene = $scene.value
|
||||
},
|
||||
|
||||
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 : ''
|
||||
this.webcam.find( select(this.selectedWebcam) )
|
||||
this.chatnetwork.find( select(this.selectedChatnetwork) )
|
||||
this.scene.find( select(this.selectedScene) )
|
||||
for( let i in plugins ){
|
||||
try{ cb(plugins[i]) }catch(e){ console.error(e) }
|
||||
}
|
||||
},
|
||||
|
||||
renderSettings(){
|
||||
let opts = {webcam: $webcam.value, chatnetwork: $chatnetwork.value, scene: $scene.value }
|
||||
let theWebcam = this.webcam.find( (p) => p.plugin.name == $webcam.value )
|
||||
let theChatnetwork = this.chatnetwork.find( (p) => p.plugin.name == $chatnetwork.value )
|
||||
let theScene = this.scene.find( (p) => p.plugin.name == $scene.value )
|
||||
this.update()
|
||||
$settings.innerHTML = ''
|
||||
$settings.appendChild(theWebcam.config(opts))
|
||||
if( theChatnetwork.plugin.name != theWebcam.plugin.name ) $settings.appendChild( theChatnetwork.config(opts) )
|
||||
if( theScene.plugin.name != theWebcam.plugin.name && theScene.plugin.name != theChatnetwork.plugin.name )
|
||||
$settings.appendChild( scene.config(opts) )
|
||||
this.forSelectedPluginsDo( (plugin) => {
|
||||
console.log("configuring "+plugin.plugin.name)
|
||||
console.dir(plugin)
|
||||
$settings.appendChild( plugin.config(opts) )
|
||||
})
|
||||
},
|
||||
|
||||
randomName(){
|
||||
var names = []
|
||||
let add = (s) => s.length < 6 && !s.match(/[0-9$]/) && !s.match(/_/) ? names.push(s) : false
|
||||
for ( var i in window ) add(i)
|
||||
for ( var i in Object.prototype ) add(i)
|
||||
for ( var i in Function.prototype ) add(i)
|
||||
for ( var i in Array.prototype ) add(i)
|
||||
for ( var i in String.prototype ) add(i)
|
||||
var a = names[Math.floor(Math.random() * names.length)];
|
||||
var b = names[Math.floor(Math.random() * names.length)];
|
||||
var c = names[Math.floor(Math.random() * names.length)];
|
||||
return String(`${a}-${b}-${c}`).toLowerCase()
|
||||
}
|
||||
|
||||
},{
|
||||
|
||||
get(data,k,v){ return data[k] },
|
||||
|
|
|
|||
|
|
@ -352,6 +352,13 @@ let utils = {
|
|||
QR.canvas = document.getElementById('qrcode')
|
||||
QR.draw( url, QR.canvas )
|
||||
},0)
|
||||
// mobile share
|
||||
if( typeof navigator.share != 'undefined'){
|
||||
navigator.share({
|
||||
url,
|
||||
title: 'your meeting link'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -444,7 +451,7 @@ $menu.css = `
|
|||
--xrf-lighter-gray: #e4e2fb96;
|
||||
--xrf-font-sans-serif: system-ui, -apple-system, segoe ui, roboto, ubuntu, helvetica, cantarell, noto sans, sans-serif;
|
||||
--xrf-font-monospace: menlo, monaco, lucida console, liberation mono, dejavu sans mono, bitstream vera sans mono, courier new, monospace, serif;
|
||||
--xrf-font-size-0: 12px;
|
||||
--xrf-font-size-0: 11px;
|
||||
--xrf-font-size-1: 14px;
|
||||
--xrf-font-size-2: 17px;
|
||||
--xrf-font-size-3: 21px;
|
||||
|
|
@ -805,19 +812,42 @@ $menu.css = `
|
|||
font-size: var(--xrf-font-size-0);
|
||||
margin-right:10px
|
||||
}
|
||||
.ruler{
|
||||
width:97%;
|
||||
margin:7px 0px;
|
||||
}
|
||||
|
||||
|
||||
a.badge {
|
||||
text-decoration:none;
|
||||
}
|
||||
|
||||
.xrf select{
|
||||
min-width: 200px;oborder-inline: none;
|
||||
min-width: 200px;
|
||||
border-inline: none;
|
||||
border-inline: none;
|
||||
border-block: none;
|
||||
border: 1px solid #AAA;
|
||||
height: 31px;
|
||||
border: 3px solid var(--xrf-primary);
|
||||
border-radius: 5px;
|
||||
background: var(--xrf-lighter-gray);
|
||||
background: none;
|
||||
border-radius:30px;
|
||||
}
|
||||
.xrf select,
|
||||
.xrf option{
|
||||
padding: 0px 16px;
|
||||
min-width: 200px;
|
||||
height: 35px;
|
||||
}
|
||||
|
||||
.xrf input{
|
||||
border-radius:30px;
|
||||
padding: 7px 15px;
|
||||
border-block: none;
|
||||
border-inline: none;
|
||||
border: 1px solid #888;
|
||||
background: transparent;
|
||||
height: 18px;
|
||||
max-width:168px;
|
||||
}
|
||||
|
||||
.xrf table tr td {
|
||||
|
|
@ -825,10 +855,18 @@ $menu.css = `
|
|||
text-align:right;
|
||||
}
|
||||
.xrf table tr td:nth-child(1){
|
||||
min-width:95px;
|
||||
min-width:115px;
|
||||
height:40px;
|
||||
padding-right:15px;
|
||||
}
|
||||
|
||||
.xrf small{
|
||||
font-size: var(--xrf-font-size-0);
|
||||
}
|
||||
.disabled{
|
||||
opacity:0.5
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
`
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ window.accessibility = (opts) => new Proxy({
|
|||
|
||||
settings(){
|
||||
this.toggle() // *TODO* should show settings screen
|
||||
if( this.enabled ) window.notify(`accessibility boosted, click <a href="#">here</a> to tweak settings`)
|
||||
},
|
||||
|
||||
speak(str, override){
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
window.network = (opts) => new Proxy({
|
||||
|
||||
connected: false,
|
||||
meetinglink: "",
|
||||
peers: {},
|
||||
plugin: {},
|
||||
opts,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
window.matrix = (opts) => new Proxy({
|
||||
|
||||
el: null, // HTML element
|
||||
|
||||
plugin:{
|
||||
type: 'network',
|
||||
name: '[matrix] channel',
|
||||
description: '[matrix] is a standardized decentralized privacy-friendly protocol',
|
||||
description: 'a standardized decentralized privacy-friendly protocol',
|
||||
url: 'https://matrix.org',
|
||||
protocol: 'matrix://',
|
||||
video: false,
|
||||
audio: false,
|
||||
chat: true,
|
||||
|
|
@ -12,14 +15,45 @@ window.matrix = (opts) => new Proxy({
|
|||
},
|
||||
|
||||
html: {
|
||||
generic: (opts) => `<table>
|
||||
generic: (opts) => `<div>
|
||||
<a href="${opts.url}" target="_blank" class="badge ruler">matrix</a>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="${opts.url}" target="_blank" class="badge">matrix</a></td>
|
||||
<td>channel</td>
|
||||
<td>
|
||||
<input type="text" id="channelname" placeholder="channel name"/>
|
||||
<input type="text" id="channel" placeholder="#xrfragment:matrix.org"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>server</td>
|
||||
<td>
|
||||
<input type="text" id="server" placeholder="https://matrix.org"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>user</td>
|
||||
<td>
|
||||
<input type="text" id="username" placeholder="@you:matrix.org"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>authenticate</td>
|
||||
<td>
|
||||
<select>
|
||||
<option>via password</option>
|
||||
<option>via access token</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>
|
||||
<input type="text" id="secret" placeholder="password or token"/>
|
||||
</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><br>
|
||||
</div>
|
||||
`
|
||||
},
|
||||
|
|
@ -29,20 +63,44 @@ window.matrix = (opts) => new Proxy({
|
|||
network.plugin['matrix'] = this
|
||||
$connections.chatnetwork = $connections.chatnetwork.concat([this])
|
||||
$connections.scene = $connections.scene.concat([this])
|
||||
this.reactToConnectionHrefs()
|
||||
},
|
||||
|
||||
connect(opts){
|
||||
console.log("connecting "+this.plugin.name)
|
||||
console.dir(opts)
|
||||
},
|
||||
|
||||
config(opts){
|
||||
opts = {...opts, ...this.plugin }
|
||||
let el = document.createElement('div')
|
||||
this.el = document.createElement('div')
|
||||
let html = this.html.generic(opts)
|
||||
for( let i in opts ){
|
||||
if( this.html[i] ) html += this.html[i](opts)
|
||||
}
|
||||
el.innerHTML = html
|
||||
el.querySelector('.badge').addEventListener('mouseover', () => {
|
||||
window.notify(`${opts.name} is ${opts.description}.<br>You can basically make up a new channelname or use an existing one`)
|
||||
this.el.innerHTML = html
|
||||
window.notify(`${opts.name} is ${opts.description}, it is the hottest internet technology available at this moment.<br>Read more about it <a href="${opts.url}" target="_blank">here</a>.<br>You can basically make up a new channelname or use an existing one`)
|
||||
return this.el
|
||||
},
|
||||
|
||||
reactToConnectionHrefs(){
|
||||
xrf.addEventListener('href', (opts) => {
|
||||
let {mesh} = opts
|
||||
if( !opts.click ) return
|
||||
if( mesh.userData.href.match(this.protocol) ){
|
||||
let parts = mesh.userData.href.replace(this.plugin.protocol,'')
|
||||
if( parts[0] == 'r' ){ // room
|
||||
$connections.$chatnetwork.value = this.plugin.name
|
||||
$connections.$scene.value = this.plugin.name
|
||||
$connections.show()
|
||||
let server = parts.split("/")[1].replace(/:.*/,'')
|
||||
let channel = parts.split("/")[1].replace(/.*:/,'')
|
||||
this.el.querySelector('#channel').value = `#${channel}:${server}`
|
||||
this.el.querySelector('#server').value = server
|
||||
console.log("configured matrix")
|
||||
}
|
||||
}else window.notify("malformed connection URI: "+mesh.userData.href)
|
||||
})
|
||||
return el
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -51,9 +109,9 @@ window.matrix = (opts) => new Proxy({
|
|||
set(data,k,v){
|
||||
let from = data[k]
|
||||
data[k] = v
|
||||
switch( k ){
|
||||
default: matrix.opts.scene.dispatchEvent({type:`matrix.${k}.change`, from, to:v})
|
||||
}
|
||||
//switch( k ){
|
||||
// default: matrix.opts.scene.dispatchEvent({type:`matrix.${k}.change`, from, to:v})
|
||||
//}
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ window.trystero = (opts) => new Proxy({
|
|||
name: 'Peer2Peer',
|
||||
description: 'P2P using WebRTC over bittorrent for signaling & encryption',
|
||||
url: 'https://github.com/dmotz/trystero',
|
||||
protocol: 'trystero://',
|
||||
video: true,
|
||||
audio: true,
|
||||
chat: true,
|
||||
|
|
@ -12,23 +13,12 @@ window.trystero = (opts) => new Proxy({
|
|||
},
|
||||
|
||||
html: {
|
||||
generic: (opts) => `<table id="trystero">
|
||||
<tr>
|
||||
<td>
|
||||
<button class="emoticon" id="randomize" aria-label="button" aria-title="randomize" onclick="$('#trystero #channelname').value = $connections.randomName()">🎲</button>
|
||||
<a href="${opts.url}" target="_blank" class="badge nomargin">P2P</a>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="channelname" placeholder="channel name"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
`
|
||||
generic: (opts) => ``
|
||||
},
|
||||
|
||||
handle: null, // { selfId: .... } when connected
|
||||
link: null,
|
||||
ip: null,
|
||||
roomid: '',
|
||||
selfId: null,
|
||||
connected: false,
|
||||
names: {},
|
||||
|
|
@ -41,17 +31,32 @@ window.trystero = (opts) => new Proxy({
|
|||
$connections.webcam = $connections.webcam.concat([this])
|
||||
$connections.chatnetwork = $connections.chatnetwork.concat([this])
|
||||
$connections.scene = $connections.scene.concat([this])
|
||||
this.reactToConnectionHrefs()
|
||||
},
|
||||
|
||||
connect(){
|
||||
connect(opts){
|
||||
// embedded https://github.com/dmotz/trystero (trystero-torrent.min.js build)
|
||||
console.log("connecting "+this.plugin.name)
|
||||
console.dir(opts)
|
||||
this.handle = joinRoom( room.config, room.link )
|
||||
this.send({message:'📡 [trystero] opening P2P WebRTC-channel via bittorrent',class:['info']})
|
||||
//this.handle = joinRoom( room.config, room.link )
|
||||
//this.send({message:'📡 [trystero] opening P2P WebRTC-channel via bittorrent',class:['info']})
|
||||
},
|
||||
|
||||
send(opts){ $chat.send({...opts, source: 'trystero'}) },
|
||||
|
||||
createLink(opts){
|
||||
this.link = document.location.href.replace(/#.*/,'')
|
||||
if( this.link.match(/localhost/) ){
|
||||
fetch('https://api.duckduckgo.com/?q=my+ip&format=json')
|
||||
.then( (res) => res.json() )
|
||||
.then( (res) => {
|
||||
const ipRegex = /Your IP address is ([0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)/g;
|
||||
const ip = ipRegex.exec(res.Answer)[1]
|
||||
this.link = this.link.replace(/localhost/, ip )
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
config(opts){
|
||||
opts = {...opts, ...this.plugin }
|
||||
let el = document.createElement('div')
|
||||
|
|
@ -59,12 +64,31 @@ window.trystero = (opts) => new Proxy({
|
|||
for( let i in opts ){
|
||||
if( this.html[i] ) html += this.html[i](opts)
|
||||
}
|
||||
el.innerHTML = html
|
||||
el.querySelector('#randomize').addEventListener('mouseover', () => window.notify("generate random channel name") )
|
||||
el.querySelector('.badge').addEventListener('mouseover', () => {
|
||||
window.notify(`${opts.name} is ${opts.description} <br>by using a serverless technology called <a href="${opts.url}" target="_blank">trystero</a>.<br>You can basically make up your own channelname or choose an existing one`)
|
||||
})
|
||||
window.notify(`${opts.name} is ${opts.description} <br>by using a serverless technology called <a href="https://webrtc.org/" target="_blank">webRTC</a> via <a href="${opts.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.`)
|
||||
// resolve ip
|
||||
if( !this.link ) this.createLink(opts)
|
||||
return el
|
||||
},
|
||||
|
||||
reactToConnectionHrefs(){
|
||||
xrf.addEventListener('href', (opts) => {
|
||||
let {mesh} = opts
|
||||
if( !opts.click ) return
|
||||
if( mesh.userData.href.match(this.protocol) ){
|
||||
let parts = mesh.userData.href.replace(this.plugin.protocol,'')
|
||||
console.dir(parts)
|
||||
if( parts[0] == 'r' ){ // room
|
||||
this.roomid = parts.split("/")[1].replace(/:.*/,'')
|
||||
this.server = parts.split("/")[1].replace(/.*:/,'')
|
||||
if( this.server != 'bittorrent' ) window.notify("only bittorrent is supported for trystero (for now) :/")
|
||||
$connections.show()
|
||||
$connections.$webcam.value = this.plugin.name
|
||||
$connections.$chatnetwork.value = this.plugin.name
|
||||
$connections.$scene.value = this.plugin.name
|
||||
console.log("configured trystero")
|
||||
}
|
||||
}else window.notify("malformed connection URI: "+mesh.userData.href)
|
||||
})
|
||||
}
|
||||
|
||||
},
|
||||
|
|
@ -74,9 +98,9 @@ window.trystero = (opts) => new Proxy({
|
|||
set(data,k,v){
|
||||
let from = data[k]
|
||||
data[k] = v
|
||||
switch( k ){
|
||||
default: trystero.opts.scene.dispatchEvent({type:`trystero.${k}.change`, from, to:v})
|
||||
}
|
||||
//switch( k ){
|
||||
// default: elcene.dispatchEvent({type:`trystero.${k}.change`, from, to:v})
|
||||
//}
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue