/* The MIT License (MIT) Copyright (c) 2014-2018 Nikolai Suslov and the Krestianstvo.org project contributors. (https://github.com/NikolaySuslov/livecodingspace/blob/master/LICENSE.md) */ //import page from '/lib/page.mjs'; import { Header } from '/web/header.js'; class IndexApp { constructor(entry) { console.log("index app constructor"); this.entry = entry; this.worlds = {}; this.instances = {}; //this.language = _LangManager.language; if (!_app.isLuminary) { this.initReflectorConnection(); } this.initHTML(); this.initUser(); document.querySelector("#userLobby")._refresh(); } initReflectorConnection() { this.options = { query: 'pathname=' + window.location.pathname.slice(1, window.location.pathname.lastIndexOf("/")), secure: window.location.protocol === "https:", reconnection: false, path: '', transports: ['websocket'] } //window.location.host var socket = io.connect(window._app.reflectorHost, this.options); const parse = (msg) => { this.parseOnlineData(msg) } socket.on('getWebAppUpdate', msg => parse.call(this, msg)); socket.on("connect", function () { let noty = new Noty({ text: 'Connected to Reflector!', timeout: 2000, theme: 'mint', layout: 'bottomRight', type: 'success' }); noty.show(); }) socket.on('connect_error', function (err) { console.log(err); var errDiv = document.createElement("div"); errDiv.innerHTML = "
Connection error to Reflector!" + err + "
"; document.querySelector('body').appendChild(errDiv); let noty = new Noty({ text: 'Connection error to Reflector! ' + err, theme: 'mint', layout: 'bottomRight', type: 'error' }); noty.show(); }); } initHTML() { let self = this; //first init from _app document.querySelector('head').innerHTML += ''; let headerGUI = new Header(); headerGUI.init(); //add HTML let entry = document.createElement("div"); entry.setAttribute("id", 'app'); document.body.appendChild(entry); let divs = ['appGUI', 'userLobby', 'main', 'worldsGUI']; divs.forEach(el => { let appEl = document.createElement("div"); appEl.setAttribute("id", el); entry.appendChild(appEl); }) document.querySelector("#worldsGUI").$cell({ id: "worldsGUI", $cell: true, $type: "div", _comps: [], _wcards: {}, $components: [], _refresh: function (comps) { //do update; //this._userAlias = user; this._comps = comps; }, $init: function () { console.log('init comp...'); }, $update: function () { //do update; console.log('update me'); this.$components = this._comps; } }); //init CELL document.querySelector("#userLobby").$cell({ id: "userLobby", $cell: true, $type: "div", $components: [], _refresh: function (){ this.$components = self.initUserGUI() }, $update: function () { } }); } async initWorldsProtosListForUser(userAlias) { let doc = document.querySelector("#worldsGUI"); //doc.$components = []; let allInfo = await _app.getAllProtoWorldsInfoForUser(userAlias);//await this.getWorldsProtosListForUser(userAlias); let worlds = this.createWorldsGUI(userAlias); worlds._refresh(allInfo); let components = [ { $type: "div", class: "mdc-layout-grid", $components: [ { $type: "div", class: "mdc-layout-grid__inner", $components: [ { $type: "div", class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12", $components: [ { $type: "h1", class: "mdc-typography--headline4", $text: 'Worlds for user: ' + userAlias } ] }, { $type: "div", class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12", $components: [worlds] } ] } ] } ]; doc._refresh(components); //initiate update world cards doc._wcards = worlds; doc._wcards.$update(); //console.log(allInfo); } async initWorldsStatesListForUser(userAlias) { let doc = document.querySelector("#worldsGUI"); //doc.$components = []; let allInfo = await _app.getAllStateWorldsInfoForUser(userAlias);//await this.getWorldsProtosListForUser(userAlias); let worlds = this.createWorldsGUI(userAlias, 'allStates'); worlds._refresh(allInfo); let components = [ { $type: "div", class: "mdc-layout-grid", $components: [ { $type: "div", class: "mdc-layout-grid__inner", $components: [ { $type: "div", class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12", $components: [ { $type: "h1", class: "mdc-typography--headline4", $text: 'States for ' + userAlias } ] }, { $type: "div", class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12", $components: [].concat(worlds) } ] } ] } ] doc._refresh(components); //initiate update world cards doc._wcards = worlds; doc._wcards.$update(); //console.log(allInfo); } authGUI(){ let alias = _LCSDB.user().is.alias; let userEl = document.querySelector('#userGUI'); userEl._status = 'Welcome ' + alias + '!'; //userEl.style.backgroundColor = '#e6e6e6'; userEl._refresh(); //$update(); //_LCSDB.user().get('profile').once(function (data) { console.log(data) }) let el = document.getElementById("loginGUI"); if (el) { el.remove(); } _LCSDB.user().get('profile').not(function (key) { let profile = { 'alias': alias }; _LCSDB.user().get('profile').put(profile); }) // not load proxy by default // _LCSDB.user().get('proxy').not(res=>{ // console.log('user has no proxy'); // window._app.loadProxyDefaults(); // }); let actionsGUI = document.querySelector('#worldActionsGUI'); if (actionsGUI) actionsGUI._refresh(); new Noty({ text: alias + ' is succesfully authenticated!', timeout: 2000, theme: 'mint', layout: 'bottomRight', type: 'success' }).show(); if(this.entry == 'index'){ //change for LiveCoding.space to 'app' this.initWorldsProtosListForUser(alias); } } initUser() { let self = this; if(_LCSDB.user().is) { self.authGUI() } else { _LCSDB.on('auth', function (ack) { if (ack.sea.pub) { self.authGUI(); } console.log(_LCSDB.user().is); }); } } initUserGUI() { let self = this; let lookWorlds = { $type: "div", id: "lookWorlds", class: "mdc-layout-grid mdc-layout-grid--align-left", _status: '', $init: function () { this._status = "init"; }, $update: function () { //change for LiveCoding.space site 'app' let defaultName = ''; let guiForAll = [ { $type: "div", style: "margin-top: 20px;", _userName: null, _userNameField: null, $components: [ _app.widgets.inputTextFieldOutlined({ "id": 'worldsUserName', "label": 'Enter user name', "value": defaultName, "type": "text", "init": function () { this._userNameField = new mdc.textField.MDCTextField(this); } }), _app.widgets.p, // { // $type: "a", // class: "mdc-button mdc-button--raised mdc-card__action actionButton", // $text: 'World Protos', //self.language.t('set proxy'),//"clone", // onclick: function (e) { // //console.log('clone'); // let searchName = this._userNameField.value; // self.initWorldsProtosListForUser(searchName); // } // }, // { // $type: "a", // class: "mdc-button mdc-button--raised mdc-card__action actionButton", // $text: 'World States', //self.language.t('set proxy'),//"clone", // onclick: function (e) { // //console.log('clone'); // let searchName = this._userNameField.value; // self.initWorldsStatesListForUser(searchName); // } // } _app.widgets.buttonRaised( { "label": 'World Protos', "onclick": function (e) { e.preventDefault(); //page("/app/worlds/protos") let searchName = this._userNameField.value; if(searchName !== "") window.location.pathname = "/"+searchName+"/worlds/protos" //_app.indexApp.getAppDetailsFromDefaultDB('protos'); } }), _app.widgets.space, _app.widgets.buttonRaised( { "label": 'World States', "onclick": function (e) { e.preventDefault(); //page("/app/worlds/states") let searchName = this._userNameField.value; if(searchName !== "") window.location.pathname = "/"+searchName+"/worlds/states" //_app.indexApp.getAppDetailsFromDefaultDB('states'); } }) ] }, // window._app.widgets.buttonStroked( // { // "label": 'Default World Protos', // "onclick": function (e) { // e.preventDefault(); // //page("/app/worlds/protos") // window.location.pathname = "/app/worlds/protos" // //_app.indexApp.getAppDetailsFromDefaultDB('protos'); // } // }), // window._app.widgets.buttonStroked( // { // "label": 'Default World States', // "onclick": function (e) { // e.preventDefault(); // //page("/app/worlds/states") // window.location.pathname = "/app/worlds/states" // //_app.indexApp.getAppDetailsFromDefaultDB('states'); // } // }) ]; this.$components = [ { $type: "h1", class: "mdc-typography--headline4", $text: "Looking for Worlds made by other Users!" } ].concat(guiForAll, _app.widgets.p, _app.widgets.divider) } } let luminaryFeature = { $cell: true, $type: 'div', class: "mdc-layout-grid mdc-layout-grid--align-left", _luminarySwitch: null, $components: [ { $type: "p", class: "mdc-typography--headline5", $text: "Use Krestianstvo Luminary (experimental)" }, { $type: 'p' }, _app.widgets.switch({ 'id': 'forceLuminary', 'init': function () { this._switch = new mdc.switchControl.MDCSwitch(this); let config = localStorage.getItem('lcs_config'); this._switch.checked = JSON.parse(config).luminary; // this._replaceSwitch = this._switch; }, 'onchange': function (e) { if (this._switch) { let chkAttr = this._switch.checked;//this.getAttribute('checked'); if (chkAttr) { let config = JSON.parse(localStorage.getItem('lcs_config')); config.luminary = true; localStorage.setItem('lcs_config', JSON.stringify(config)); window.location.reload(true); //this._switch.checked = false; } else { let config = JSON.parse(localStorage.getItem('lcs_config')); config.luminary = false; localStorage.setItem('lcs_config', JSON.stringify(config)); window.location.reload(true); } } } } ), { $type: 'label', for: 'input-forceLuminary', $text: 'Off / On' } ] } let userGUI = { $type: "div", id: "userGUI", // style:"background-color: #ffeb3b", class: "mdc-layout-grid mdc-layout-grid--align-left", _status: "Welcome!", $init: function () { //this._status = "Welcome!" this._status = 'Welcome !'; //userEl.style.backgroundColor = '#e6e6e6'; this._refresh(); //$update(); }, $update: function () {}, _refresh: function () { var gui = {}; if (_LCSDB.user().is) { gui = [ window._app.widgets.buttonRaised( { "label": 'Sign OUT', "onclick": function (e) { _LCSDB.user().leave(); setTimeout(() => { //window.sessionStorage.removeItem('alias'); //window.sessionStorage.removeItem('tmp'); window.location.reload(true); }, 1); } }), { $type: "p" }, window._app.widgets.buttonStroked( { "label": 'PROFILE', "onclick": function (e) { e.preventDefault(); //page("/profile") window.location.pathname = "/profile" } }), { $type: "p" }, window._app.widgets.buttonStroked( { "label": 'My World protos', "onclick": function (e) { e.preventDefault(); let alias = _LCSDB.user().is.alias; window.location.pathname = '/' + alias + '/worlds/protos' //page('/' + alias + '/worlds/protos'); //_app.indexApp.getWorldsProtosFromUserDB(alias); } }), window._app.widgets.buttonStroked( { "label": 'My World states', "onclick": function (e) { e.preventDefault(); let alias = _LCSDB.user().is.alias; window.location.pathname = '/' + alias + '/worlds/states' //page('/' + alias + '/worlds/states'); // page.redirect('/' + alias + '/worlds/states'); //_app.indexApp.getWorldsFromUserDB(alias); } }) ] } this.$components = [ _app.widgets.emptyDiv, window._app.widgets.buttonRaised( { "label": 'Connection settings', "onclick": function (e) { e.preventDefault(); window.location.pathname = '/settings'; } }), _app.widgets.emptyDiv, _app.widgets.divider, { $type: "h1", class: "mdc-typography--headline3", $text: this._status } ].concat(gui) } } let loginGUI = { $type: "div", id: "loginGUI", //style:"background-color: #efefef", class: "mdc-layout-grid mdc-layout-grid--align-left", _alias: null, _pass: null, _passField: null, _aliasField: null, _initData: function () { this._alias = ''; this._pass = ''; // if (window.sessionStorage.getItem('alias')) { // this._alias = window.sessionStorage.getItem('alias') // } // if (window.sessionStorage.getItem('tmp')) { // this._pass = window.sessionStorage.getItem('tmp') // } }, $init: function () { this._initData(); }, $update: function () { this.$components = [ { $type: "div", class: "mdc-layout-grid__inner", $components: [ { $type: "div", class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12", $components: [ { $type: "span", class: "mdc-typography--headline5", $text: "Login: " }, window._app.widgets.inputTextFieldOutlined({ "id": 'aliasInput', "label": "Login", "value": this._alias, "type": "text", "init": function () { this._aliasField = new mdc.textField.MDCTextField(this); } }), ] }, { $type: "div", class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12", $components: [ { $type: "span", class: "mdc-typography--headline5", $text: "Password: " }, window._app.widgets.inputTextFieldOutlined({ "id": 'passwordInput', "label": "Password", "value": this._pass, "type": "password", "init": function () { this._passField = new mdc.textField.MDCTextField(this); } }), ] }, { $type: "div", class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12", $components: [ window._app.widgets.buttonRaised( { "label": 'Sign UP', "onclick": function (e) { e.preventDefault(); let alias = this._aliasField.value; let pass = this._passField.value if (pass.length < 7) { new Noty({ text: "Your passphrase needs to be longer than 7 letters", timeout: 2000, theme: 'mint', layout: 'bottomRight', type: 'error' }).show(); } else { // _LCSDB.user().create(alias, pass, function (ack) { if (!ack.wait) { } if (ack.err) { console.log(ack.err) return ack.err }; if (ack.pub) { let userObj = { 'alias': alias, 'pub': ack.pub }; _LCSDB.get('users').get(alias).put(userObj); } _LCSDB.user().auth(alias, pass); }); } } }), _app.widgets.space, window._app.widgets.buttonRaised( { "label": 'Sign IN', "onclick": function (e) { e.preventDefault(); let alias = this._aliasField.value; let pass = this._passField.value _app.helpers.authUser(alias, pass); // _LCSDB.user().auth.call(_LCSDB, alias, pass // // , function(ack) { // // if (ack.err) { // // new Noty({ // // text: ack.err, // // timeout: 2000, // // theme: 'mint', // // layout: 'bottomRight', // // type: 'error' // // }).show(); // // } // //} // ); } }) ] } ] } ] } } return [luminaryFeature, userGUI, loginGUI, _app.widgets.divider, lookWorlds] } refresh() { // socket.emit('getWebAppUpdate', ""); } parseOnlineData(data) { let parcedData = _app.parseAppInstancesData(data); //if (Object.entries(parcedData).length !== 0) let onlineGUIs = document.querySelectorAll('.online'); onlineGUIs.forEach(function (item) { item._refresh(parcedData) }); } createWorldCard(id, type) { let self = this; let onlineGUI = { $cell: true, id: "onlineGUI_" + id, class: "online", $type: "div", _instances: {}, _worldListItem: function (m) { return { $type: "li", class: "mdc-list-item", $components: [ { $type: "span", class: "world-link mdc-list-item__text", $components: [ { $type: "span", class: "mdc-list-item__primary-text", $components: [ { $type: "a", $text: m[0], //target: "_blank", // href: window.location.protocol + "//" + window.location.host + "/" + m[1].user + m[0], onclick: function (e) { self.checkForManualSettings(); window.location.pathname = "/" + m[1].user + m[0]; //self.refresh(); } }, ] }, { $type: "span", class: "mdc-list-item__secondary-text", $text: _app.isLuminary ? _LangManager.language.t('users') + Object.keys(m[1].clients).length : _LangManager.language.t('users') + m[1].clients } ] } ] } }, $components: [], _refresh: function (data) { if (data) { if (Object.entries(data).length !== 0) { if (this._worldInfo) { let insts = Object.entries(data).filter(el => el[0] == this._worldInfo.worldName); if (insts.length !== 0) this._instances = insts[0][1]; } } else { this._instances = {} } } }, $init: function () { if (_app.isLuminary) { let luminaryPath = _app.luminaryPath; let ref = _LCSDB.get(luminaryPath); setInterval(function () { ref.get('allclients').once().map().once(res => { if (res) { if (res.id) { let clientTime = Gun.state.is(res, 'live'); let now = Gun.time.is(); if (now - clientTime < 10000) { let instance = res.user + res.instance; //let data = JSON.stringify({[res.instance]: {instance: instance, clients: {}, user: res.user, loadInfo: {}}}); //console.log(data); if (!self.instances[res.instance]) { self.instances[res.instance] = { id: res.instance, instance: instance, clients: { [res.id]: res }, user: res.user, loadInfo: {} } } else { self.instances[res.instance].clients[res.id] = res } let data = JSON.stringify(self.instances); self.parseOnlineData(data); } else { if (self.instances[res.instance]) { delete self.instances[res.instance].clients[res.id]; if (Object.keys(self.instances[res.instance].clients).length == 0) { delete self.instances[res.instance]; self.parseOnlineData(JSON.stringify({})); } } //ref.get('instances').get(res.instance).get(res.id).put(null); } } } } ) }, 5000); } this._refresh(); }, $update: function () { if (this._instances) { let cardListData = Object.entries(this._instances).filter(el => el[1].user == this._worldInfo.userAlias); this.$components = [ { $type: "hr", class: "mdc-list-divider" } ].concat(cardListData.map(this._worldListItem)) } } } return { $cell: true, id: 'worldCard_' + id, $type: "div", _worldInfo: {}, _refresh: function (data) { this._worldInfo = data }, $init: function () { //get space for user // if (!saveName) { // this._getWorldInfo(); // } else { // this._getStateInfo(); // } }, $update: function () { //console.log(this._worldInfo); //this.$components = [this._updateCard()] }, _updateComps: function () { //console.log(this._worldInfo); this.$components = [this._updateCard()] }, _updateCard: function () { let desc = this._worldInfo; if (!desc || Object.keys(desc).length == 0) { return { $type: "h1", class: "mdc-typography--headline4", $text: "ERROR: NO WORLD!" } } let userGUI = []; let online = []; let cardInfo = { "title": "" }; if (type == "full") { } else { userGUI.push({ $type: "a", class: "mdc-button mdc-button--compact mdc-card__action mdc-button--outlined", $text: "Details", onclick: function (e) { e.preventDefault(); window.location.pathname = "/" + desc.userAlias + '/' + desc.worldName + '/about' } }); } userGUI.push({ $type: "a", class: "mdc-button mdc-button--raised mdc-card__action ", $text: _LangManager.language.t('start'),//"Start new", //target: "_blank", //href: "/" + desc.userAlias + '/' + desc.worldName, onclick: function (e) { self.checkForManualSettings(); window.location.pathname = "/" + desc.userAlias + '/' + desc.worldName //self.refresh(); } }); if (desc.type == 'saveState') { cardInfo.title = desc.worldName.split('/')[2]; } if (desc.type == 'proto') { cardInfo.title = desc.worldName; // userGUI.push( // { // $type: "a", // class: "mdc-button mdc-button--compact mdc-card__action", // $text: "States", // onclick: async function (e) { // e.preventDefault(); // window.location.pathname = "/" + desc.userAlias + '/' + desc.worldName +'/about' // //console.log('clone'); // // document.querySelector('#worldStatesGUI')._refresh({}); // // let data = await _app.getSaveStates(desc.userAlias, desc.worldName); // // document.querySelector('#worldStatesGUI')._refresh(data); // } // } // ) } online.push(onlineGUI); if(!desc.info){ desc.info = { imgUrl: "/defaults/worlds/webrtc/webimg.jpg", text: "..no text", title: "..no title" } } return { $type: "div", class: "mdc-card world-card", $components: [ { $type: "section", class: "mdc-card__media world-card__16-9-media", $init: function () { if (desc.info.imgUrl !== "") { this.style.backgroundImage = 'linear-gradient(0deg, rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.3) ), url(' + desc.info.imgUrl + ')'; } } }, { $type: "section", class: "mdc-card__primary", $components: [ { $type: "h1", class: "mdc-card__title mdc-card__title--large", $text: desc.info.title }, { $type: "h2", class: "mdc-card__subtitle mdc-theme--text-secondary-on-background", $text: desc.info.text }, { $type: "span", class: "mdc-card__subtitle mdc-theme--text-secondary-on-background", $text: 'id: ' }, { $type: "input", type: "text", disabled: "", style: "font-size:18px", value: cardInfo.title }, { $type: "p", }, { $type: "span", class: "mdc-card__subtitle mdc-theme--text-secondary-on-background", $text: 'created: ' + (new Date(desc.created)).toUTCString() }, { $type: "p", } // ,{ // $type: "span", // class: "mdc-card__subtitle mdc-theme--text-secondary-on-background", // $text: 'modified: ' + (new Date(desc[5])).toUTCString() // } ] }, { $type: "section", class: "mdc-card__actions", $components: [ ].concat(userGUI) }, { $type: "section", class: "mdc-card__actions", $components: [ { $type: 'div', $text: 'online now: ' } ].concat(online) } ] } } } } createWorldsGUI(userAlias, worldName) { let self = this; let id = worldName ? worldName + '_' + userAlias : "allWorlds_" + userAlias let headerText = worldName ? 'States for ' + worldName : 'All Worlds Protos' let worldCards = { $cell: true, id: id, $type: "div", $components: [], _states: {}, _refresh: function (data) { this._states = data }, $init: async function () { //this._refresh(); }, _makeWorldCard: function (data) { let cardID = data[1].userAlias + '_' + data[1].worldName + '_' + data[0]; let card = self.createWorldCard(cardID, 'min'); card._refresh(data[1]); //card._worldInfo = data[1]; card._updateComps(); return { $cell: true, $type: "div", class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-4", $components: [ card //self.createWorldCard(data[1].userAlias, data[1].worldName, data[0]) //this._worldCardDef(appInfo) ] } //console.log(data); }, $update: function () { let cards = Object.entries(this._states) .filter(el => Object.keys(el[1]).length !== 0) .sort(function (el1, el2) { return parseInt(el2[1].created) - parseInt(el1[1].created) }) .map(this._makeWorldCard); this.$components = [ { $type: "div", class: "mdc-layout-grid", $components: [ { $type: "div", class: "mdc-layout-grid__inner", $components: [ { $type: "div", class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12", $components: [ { $type: "H3", $text: headerText } ] } ] }, { $type: "div", class: "mdc-layout-grid__inner", $components: cards } ] } ] } } return worldCards } checkForManualSettings() { console.log("check for manual settings"); let manualSettings = localStorage.getItem('lcs_app_manual_settings'); if (manualSettings) { localStorage.removeItem('lcs_app_manual_settings'); } let el = document.querySelector('#runWorldGUI'); if (el) { if (el._arSwitch.checked) { let arSettings = { model: { 'vwf/model/aframe': null }, view: { 'vwf/view/aframe': null, 'vwf/view/editor-new': null } } localStorage.setItem('lcs_app_manual_settings', JSON.stringify(arSettings)); } if (el._turnArOnSwitch.checked) { let arSettings = { model: { 'vwf/model/aframe': null }, view: { 'vwf/view/aframe': null, 'vwf/view/aframe-ar-driver': null } } localStorage.setItem('lcs_app_manual_settings', JSON.stringify(arSettings)); } } } } export { IndexApp as default } //export {getAppDetails, generateFrontPage, setLanguage, initLocale};