diff --git a/example/aframe/sandbox/index.html b/example/aframe/sandbox/index.html index 8d1e280..dffcb21 100644 --- a/example/aframe/sandbox/index.html +++ b/example/aframe/sandbox/index.html @@ -86,6 +86,7 @@ + diff --git a/make b/make index 970ab19..def37ea 100755 --- a/make +++ b/make @@ -123,10 +123,11 @@ build(){ cp src/3rd/js/plugin/frontend/\$editor.js dist/xrfragment.plugin.editor.js cp src/3rd/js/plugin/frontend/css.js dist/xrfragment.plugin.frontend.css.js - jscat src/3rd/js/plugin/frontend/{snackbar,accessibility,\$menu,frontend,chatcommand/*,joystick,tab-to-href,remotestorage}.js > dist/xrfragment.plugin.frontend.js + jscat src/3rd/js/plugin/frontend/{snackbar,accessibility,\$menu,\$files,frontend,chatcommand/*,joystick,tab-to-href}.js > dist/xrfragment.plugin.frontend.js jscat src/3rd/js/plugin/matrix/{matrix-crdt,matrix}.js > dist/xrfragment.plugin.matrix.js jscat src/3rd/js/plugin/p2p/{trystero-torrent.min,trystero}.js > dist/xrfragment.plugin.p2p.js + jscat src/3rd/js/plugin/remotestorage/*.js > dist/xrfragment.plugin.remotestorage.js # all in one cat dist/aframe.min.js dist/aframe-blink-controls.min.js dist/xrfragment.aframe.js > dist/xrfragment.aframe.all.js diff --git a/src/3rd/js/plugin/frontend/$files.js b/src/3rd/js/plugin/frontend/$files.js new file mode 100644 index 0000000..f32fc37 --- /dev/null +++ b/src/3rd/js/plugin/frontend/$files.js @@ -0,0 +1,113 @@ + +// reactive component for displaying the menu +filesComponent = (el) => new Proxy({ + + html: (data) => ` + + +
+
+
+
+ +
+
+ ${data.tabs.map( (t) => + ` + + ` + ).join('') + } +

+
+
+ + +
+
+
+
+
+
+
+ `, + + tabs: [ + {name: "local files", id: "localFiles"} + ], + + show: false, + $localFiles: $localFiles = el.querySelector("#localFiles"), + + toggle(state){ + this.show = state !== undefined ? state : !this.show + }, + + init(opts){ + this.decorateFileButton() + // create HTML element + el.innerHTML = this.html(this) + for( i in this ) el[i] = this[i] + this.toggle(this.show) // trigger visibility + document.querySelector("#messages").appendChild(el); + // setup input listeners + (['click']).map( (e) => el.addEventListener(e, (ev) => this[e] && this[e](ev.target.id,ev) ) ) + + // signal ready + setTimeout( () => { + document.dispatchEvent( new CustomEvent("$files:ready", {detail: {$files:this,xrf}}) ) + },100) + return this + }, + + decorateFileButton: function(){ + // rename button + document.querySelector("#load").setAttribute("value","3D file") + // decorate fileLoaders + window.frontend.fileLoaders = ( (fileLoaders) => { + this.fileLoader = fileLoaders + return () => this.toggle() + })( window.frontend.fileLoaders ) + }, + + click(id,e){ + switch(id){ + case "icon": + case "more": return this.toggle(); break; + } + } +}, +{ + + get(me,k,v){ return me[k] }, + + set(me,k,v){ + me[k] = v + switch( k ){ + case "show":{ + el.style.display = v ? '' : 'none'; + if( v ) $chat.visible = true + break; + } + case "tabs":{ + el.innerHTML = $files.html($files) + break; + } + } + }, + + renderButtons: (data) => `${data.buttons.join('')}` + +}) + +// reactify component! +document.addEventListener('$chat:ready', (e) => { + window.$files = filesComponent( document.createElement('div') ).init(e.detail) +}) diff --git a/src/3rd/js/plugin/frontend/css.js b/src/3rd/js/plugin/frontend/css.js index 6a0f430..ba6ff6a 100644 --- a/src/3rd/js/plugin/frontend/css.js +++ b/src/3rd/js/plugin/frontend/css.js @@ -740,6 +740,7 @@ document.head.innerHTML += ` box-sizing: border-box; position: relative; display: inline-block; + margin-right:5px; transform: scale(var(--ggs,1)) translate(3px,3px); width: 16px; height: 6px; @@ -847,5 +848,47 @@ document.head.innerHTML += ` left: -11px; top: -2px } + + .gg-software-upload { + box-sizing: border-box; + position: relative; + display: inline-block; + margin-right:5px; + transform: scale(var(--ggs, 1)); + width: 16px; + height: 6px; + border: 2px solid; + border-top: 0; + border-bottom-left-radius: 2px; + border-bottom-right-radius: 2px; + margin-top: 8px; + } + .gg-software-upload::after { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + width: 8px; + height: 8px; + border-left: 2px solid; + border-top: 2px solid; + transform: rotate(45deg); + left: 2px; + bottom: 4px; + } + .gg-software-upload::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + border-radius: 3px; + width: 2px; + height: 10px; + background: currentColor; + left: 5px; + bottom: 3px; + } + + ` diff --git a/src/3rd/js/plugin/frontend/filedialog.js b/src/3rd/js/plugin/frontend/filedialog.js new file mode 100644 index 0000000..fd85c00 --- /dev/null +++ b/src/3rd/js/plugin/frontend/filedialog.js @@ -0,0 +1,94 @@ + +// reactive component for displaying the menu +filesComponent = (el) => new Proxy({ + + html: ` +
+
+
+
+ +
+
+ + + +
+
+ Peer2Peer
+ + + + + +
nickname + +
+
+
+ + + + + +
+ +
+
+
+
+
+
+
+ `, + + collapsed: false, + $localFiles: $localFiles = el.querySelector("#localFiles"), + + toggle(state){ + this.collapsed = state !== undefined ? state : !this.collapsed + }, + + init(opts){ + el.innerHTML = this.html + document.querySelector("#messages").appendChild(el); + (['click']).map( (e) => el.addEventListener(e, (ev) => this[e] && this[e](ev.target.id,ev) ) ) + setTimeout( () => { + document.dispatchEvent( new CustomEvent("$files:ready", {detail: {$files:this,xrf}}) ) + },100) + return this + }, + + click(id,e){ + switch(id){ + case "icon": + case "more": return this.toggle(); break; + } + this.toggle(false) + } +}, +{ + + get(me,k,v){ return me[k] }, + + set(me,k,v){ + me[k] = v + switch( k ){ + case "buttons": el.querySelector("#buttons").innerHTML = this.renderButtons(me); + document.dispatchEvent( new CustomEvent("$menu:buttons:render", {detail: el.querySelector('.menu') }) ) + break; + case "collapsed": + el.querySelector("#buttons").style.display = me.collapsed ? 'block' : 'none' + frontend.emit('$menu:collapse', v) + break; + } + }, + + renderButtons: (data) => `${data.buttons.join('')}` + +}) + +// reactify component! +document.addEventListener('frontend:ready', (e) => { + window.$files = filesComponent( document.createElement('div') ).init(e.detail) +}) diff --git a/src/3rd/js/plugin/frontend/remotestorage.js b/src/3rd/js/plugin/frontend/remotestorage.js deleted file mode 100644 index 5176db6..0000000 --- a/src/3rd/js/plugin/frontend/remotestorage.js +++ /dev/null @@ -1,84 +0,0 @@ -// this demonstrates the remotestorage aframe component - - -document.addEventListener('frontend:ready', (e) => { - - function loadScript(cb){ - let el = document.createElement("script") - el.setAttribute("defer","") - el.src = "https://unpkg.com/remotestoragejs@2.0.0-beta.7/release/remotestorage.js" - document.head.appendChild(el) - - el = document.createElement("script") - el.src = "https://unpkg.com/remotestorage-widget@1.6.0/build/widget.js" - el.addEventListener('load', () => setTimeout(cb,2000) ) - document.head.appendChild(el) - } - - function addStyles(){ - let el = document.createElement('style') - el.type = 'text/css' - el.innerHTML = ` - - #remotestorage-widget { - left: 0; - position: fixed; - display:block; - } - body.menu #remotestorage-widget{ - top: 50px; - } - body #remotestorage-widget { - top: 0px; - } - ` - document.head.appendChild(el) - } - - function addButtons(){ - const $widget = document.querySelector(".rs-widget") - debugger - - const $btnLoad = document.createElement('button') - const $btnSave = document.createElement('button') - $btnLoad.innerText = 'load' - $btnSave.innerText = 'save' - $widget.appendChild($btnLoad) - $widget.appendChild($btnSave) - } - - function init(){ - let apis = {} - window.remoteStorage = new RemoteStorage({logging: true }) - if( Object.keys(apis).length ) remoteStorage.setApiKeys(apis) - - remoteStorage.on('connected', (e) => { console.log("connected") } ) - //remoteStorage.on('network-offline', (e) => this.el.sceneEl.emit('remoteStorage.network-offline',e) ) - //remoteStorage.on('network-online', (e) => this.el.sceneEl.emit('remoteStorage.network-online',e) ) - //remoteStorage.on('error', (e) => this.el.sceneEl.emit('remoteStorage.error',e) ) - //remoteStorage.on('ready', (e) => { } ) - - remoteStorage.access.claim( `webxr`, 'rw'); // our data dir - remoteStorage.caching.enable( `/webxr/` ) // local-first, remotestorage-second - - } - - addStyles() - loadScript(init) - - // decorate fileLoaders - window.frontend.fileLoaders = (function(fileLoaders){ - return function(){ - // show rs widgets - if( !document.querySelector("#remotestorage-widget") ){ - let opts = {} - opts.modalBackdrop = false - widget = new window.Widget(window.remoteStorage, opts) - widget.attach(); - addButtons() - } - - //fileLoaders() - } - })( window.frontend.fileLoaders ) -}) diff --git a/src/3rd/js/plugin/remotestorage/remotestorage.js b/src/3rd/js/plugin/remotestorage/remotestorage.js new file mode 100644 index 0000000..53287ca --- /dev/null +++ b/src/3rd/js/plugin/remotestorage/remotestorage.js @@ -0,0 +1,105 @@ +// this demonstrates the remotestorage aframe component + +// reactive component for displaying the menu +remoteStorageComponent = (el) => new Proxy({ + + html: ` + + +
+
+

+ + +
+ `, + + show: false, + + toggle(state){ + this.show = state !== undefined ? state : !this.show + }, + + init(opts){ + // create HTML element + $files.tabs = $files.tabs.concat({id:"remoteFiles", name: "remote files"}) + el.innerHTML = this.html + el.className = "tab" + this.toggle(this.show) // trigger visibility + document.querySelector("#files .tab-frame").appendChild(el); + + // setup input listeners + (['click']).map( (e) => el.addEventListener(e, (ev) => typeof this[e] == 'function' && this[e](ev.target.id,ev) ) ) + + // signal ready + setTimeout( () => { + document.dispatchEvent( new CustomEvent("remotestorage:ready", {detail: {$files:this,xrf}}) ) + },100) + + this.loadScript( () => this.initRemoteStorage() ) + + return this + }, + + loadScript(cb){ + let el = document.createElement("script") + el.setAttribute("defer","") + el.src = "https://unpkg.com/remotestoragejs@2.0.0-beta.7/release/remotestorage.js" + document.head.appendChild(el) + + el = document.createElement("script") + el.src = "https://unpkg.com/remotestorage-widget@1.6.0/build/widget.js" + el.addEventListener('load', () => setTimeout(cb,2000) ) + document.head.appendChild(el) + }, + + initRemoteStorage(){ + let apis = { + dropbox: "4jc8nx1lbarp472" + } + window.remoteStorage = new RemoteStorage({logging: true }) + if( Object.keys(apis).length ) remoteStorage.setApiKeys(apis) + + remoteStorage.on('connected', (e) => { console.log("connected") } ) + //remoteStorage.on('network-offline', (e) => this.el.sceneEl.emit('remoteStorage.network-offline',e) ) + //remoteStorage.on('network-online', (e) => this.el.sceneEl.emit('remoteStorage.network-online',e) ) + //remoteStorage.on('error', (e) => this.el.sceneEl.emit('remoteStorage.error',e) ) + //remoteStorage.on('ready', (e) => { } ) + + remoteStorage.access.claim( `webxr`, 'rw'); // our data dir + remoteStorage.caching.enable( `/webxr/` ) // local-first, remotestorage-second + + // create widget + let opts = {} + opts.modalBackdrop = false + widget = new window.Widget(window.remoteStorage, opts) + widget.attach( "rswidget" ); + + }, + + click(id,e){ + switch(id){ + case "icon": + case "more": return this.toggle(); break; + } + this.toggle(false) + } +}, +{ + + get(me,k,v){ return me[k] }, + + set(me,k,v){ + me[k] = v + }, + +}) + +// reactify component! +document.addEventListener('$files:ready', (e) => { + window.$remotestorage = remoteStorageComponent( document.createElement('div') ).init(e.detail) +})