index-app.js 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167
  1. /*
  2. The MIT License (MIT)
  3. Copyright (c) 2014-2018 Nikolai Suslov and the Krestianstvo.org project contributors. (https://github.com/NikolaySuslov/livecodingspace/blob/master/LICENSE.md)
  4. */
  5. //import page from '/lib/page.mjs';
  6. import { Header } from '/web/header.js';
  7. class IndexApp {
  8. constructor() {
  9. console.log("app constructor");
  10. this.worlds = {};
  11. this.instances = {};
  12. //this.language = _LangManager.language;
  13. if(!_app.isLuminary){
  14. this.initReflectorConnection();
  15. }
  16. }
  17. initReflectorConnection(){
  18. this.options = {
  19. query: 'pathname=' + window.location.pathname.slice(1,
  20. window.location.pathname.lastIndexOf("/")),
  21. secure: window.location.protocol === "https:",
  22. reconnection: false,
  23. path: '',
  24. transports: ['websocket']
  25. }
  26. //window.location.host
  27. var socket = io.connect(window._app.reflectorHost, this.options);
  28. const parse = (msg) => {
  29. this.parseOnlineData(msg)
  30. }
  31. socket.on('getWebAppUpdate', msg => parse.call(this, msg));
  32. socket.on("connect", function () {
  33. let noty = new Noty({
  34. text: 'Connected to Reflector!',
  35. timeout: 2000,
  36. theme: 'mint',
  37. layout: 'bottomRight',
  38. type: 'success'
  39. });
  40. noty.show();
  41. })
  42. socket.on('connect_error', function (err) {
  43. console.log(err);
  44. var errDiv = document.createElement("div");
  45. errDiv.innerHTML = "<div class='vwf-err' style='z-index: 10; position: absolute; top: 80px; right: 50px'>Connection error to Reflector!" + err + "</div>";
  46. document.querySelector('body').appendChild(errDiv);
  47. let noty = new Noty({
  48. text: 'Connection error to Reflector! ' + err,
  49. theme: 'mint',
  50. layout: 'bottomRight',
  51. type: 'error'
  52. });
  53. noty.show();
  54. });
  55. }
  56. initHTML() {
  57. let self = this;
  58. //first init from _app
  59. document.querySelector('head').innerHTML += '<link rel="stylesheet" href="/web/index-app.css">';
  60. let headerGUI = new Header();
  61. headerGUI.init();
  62. //add HTML
  63. let entry = document.createElement("div");
  64. entry.setAttribute("id", 'app');
  65. document.body.appendChild(entry);
  66. let divs = ['appGUI', 'userLobby', 'main', 'worldsGUI'];
  67. divs.forEach(el => {
  68. let appEl = document.createElement("div");
  69. appEl.setAttribute("id", el);
  70. entry.appendChild(appEl);
  71. })
  72. //init CELL
  73. document.querySelector("#userLobby").$cell({
  74. id: "userLobby",
  75. $cell: true,
  76. $type: "div",
  77. $components: [],
  78. $update: function () {
  79. this.$components = self.initUserGUI()
  80. }
  81. });
  82. document.querySelector("#worldsGUI").$cell({
  83. id: 'worldsGUI',
  84. $cell: true,
  85. $type: "div",
  86. $components: [],
  87. _comps: [],
  88. _refresh: async function (data, fn) {
  89. _app.showProgressBar();
  90. this._comps = await fn.call(self, data);
  91. this.$update();
  92. _app.hideProgressBar();
  93. },
  94. $update: async function () {
  95. this.$components = this._comps
  96. }
  97. });
  98. }
  99. async generateFrontPage() {
  100. let infoEl = document.createElement("div");
  101. infoEl.setAttribute("id", "indexPage");
  102. let lang = _LangManager.locale;
  103. let infoElHTML = await _app.helpers.getHtmlText('/web/locale/' + lang + '/index.html');
  104. infoEl.innerHTML = infoElHTML;
  105. document.body.appendChild(infoEl);
  106. document.querySelector('#ruLang').addEventListener('click', function (e) {
  107. _LangManager.locale = 'ru';
  108. window.location.reload(true);
  109. });
  110. document.querySelector('#enLang').addEventListener('click', function (e) {
  111. _LangManager.locale = 'en';
  112. window.location.reload(true);
  113. });
  114. }
  115. initApp() {
  116. // let appElHTML = await _app.helpers.getHtmlText('/web/app.html');
  117. // appEl.innerHTML = appElHTML;
  118. // document.body.appendChild(appEl);
  119. this.initUser();
  120. document.querySelector("#userLobby").$update();
  121. //this.initWorldsListGUI();
  122. //this.getAppDetailsFromDB();
  123. }
  124. async initWorldsProtosListForUser(userAlias) {
  125. document.querySelector("#worldsGUI").$components = [];
  126. await document.querySelector("#worldsGUI")._refresh(userAlias, this.getWorldsProtosListForUser);
  127. }
  128. async initWorldsStatesListForUser(userAlias) {
  129. document.querySelector("#worldsGUI").$components = [];
  130. await document.querySelector("#worldsGUI")._refresh(userAlias, this.getWorldsStatesListForUser);
  131. }
  132. async getWorldsStatesListForUser(userAlias) {
  133. let worldsGUI = [];
  134. let worlds = this.createWorldsGUI(userAlias, 'allStates' );
  135. await _app.getAllStateWorldsInfoForUser(userAlias, function (data) {
  136. let doc = document.querySelector("#allStates_" + userAlias);
  137. if (doc) {
  138. Object.assign(doc._states, data);
  139. doc.$update();
  140. }
  141. }
  142. );
  143. worldsGUI.push(worlds);
  144. // Object.entries(data).forEach(el => {
  145. // let worlds = this.createWorldsGUI(userAlias, el[0]);
  146. // worlds._states = el[1];
  147. // worlds.$update();
  148. // worldsGUI.push(worlds);
  149. // })
  150. return [
  151. {
  152. $type: "div",
  153. class: "mdc-layout-grid",
  154. $components: [
  155. {
  156. $type: "div",
  157. class: "mdc-layout-grid__inner",
  158. $components: [
  159. {
  160. $type: "div",
  161. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  162. $components: [
  163. {
  164. $type: "h1",
  165. class: "mdc-typography--headline4",
  166. $text: 'States for ' + userAlias
  167. }
  168. ]
  169. },
  170. {
  171. $type: "div",
  172. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  173. $components: [].concat(worldsGUI)
  174. }
  175. ]
  176. }
  177. ]
  178. }
  179. ]
  180. }
  181. async getWorldsProtosListForUser(userAlias) {
  182. let worldsGUI = [];
  183. //let data = await _app.getAllProtoWorldsInfoForUser(userAlias);
  184. let worlds = this.createWorldsGUI(userAlias);
  185. await _app.getAllProtoWorldsInfoForUser(userAlias, function (data) {
  186. let doc = document.querySelector("#allWorlds_" + userAlias);
  187. if (doc) {
  188. Object.assign(doc._states, data);
  189. doc.$update();
  190. }
  191. })
  192. //worlds._states = data;
  193. //worlds.$update();
  194. worldsGUI.push(worlds);
  195. return [
  196. {
  197. $type: "div",
  198. class: "mdc-layout-grid",
  199. $components: [
  200. {
  201. $type: "div",
  202. class: "mdc-layout-grid__inner",
  203. $components: [
  204. {
  205. $type: "div",
  206. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  207. $components: [
  208. {
  209. $type: "h1",
  210. class: "mdc-typography--headline4",
  211. $text: 'Worlds for ' + userAlias
  212. }
  213. ]
  214. },
  215. {
  216. $type: "div",
  217. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  218. $components: [].concat(worldsGUI)
  219. },
  220. ]
  221. }
  222. ]
  223. }
  224. ]
  225. }
  226. initUser() {
  227. _LCSDB.on('auth', function(ack) {
  228. if (ack.sea.pub) {
  229. let alias = _LCSDB.user().is.alias;
  230. let userEl = document.querySelector('#userGUI');
  231. userEl._status = 'Welcome ' + alias + '!';
  232. //userEl.style.backgroundColor = '#e6e6e6';
  233. userEl.$update();
  234. // document.querySelector('#worldGUI').$update();
  235. // document.querySelector('#main').$update();
  236. _LCSDB.get('users').get(alias).not(function(res) {
  237. let userObj = {
  238. alias: alias,
  239. pub: ack.sea.pub
  240. }
  241. _LCSDB.get('users').get(alias).put(userObj);
  242. })
  243. _LCSDB.user().get('profile').once(function (data) { console.log(data) })
  244. let el = document.getElementById("loginGUI");
  245. if (el) {
  246. el.remove();
  247. }
  248. _LCSDB.user().get('profile').not(function (key) {
  249. let profile = { 'alias': alias };
  250. _LCSDB.user().get('profile').put(profile);
  251. })
  252. let actionsGUI = document.querySelector('#worldActionsGUI');
  253. if (actionsGUI)
  254. actionsGUI._refresh();
  255. new Noty({
  256. text: alias + ' is succesfully authenticated!',
  257. timeout: 2000,
  258. theme: 'mint',
  259. layout: 'bottomRight',
  260. type: 'success'
  261. }).show();
  262. //this.getAppDetailsFromUserDB();
  263. }
  264. console.log(_LCSDB.user().is);
  265. });
  266. }
  267. initUserGUI() {
  268. let worldGUI =
  269. {
  270. $type: "div",
  271. id: "worldGUI",
  272. class: "mdc-layout-grid mdc-layout-grid--align-left",
  273. _status: '',
  274. $init: function () {
  275. this._status = "init";
  276. },
  277. $update: function () {
  278. let guiForAll = [
  279. window._app.widgets.buttonStroked(
  280. {
  281. "label": 'Default World Protos',
  282. "onclick": function (e) {
  283. e.preventDefault();
  284. //page("/app/worlds/protos")
  285. window.location.pathname = "/app/worlds/protos"
  286. //_app.indexApp.getAppDetailsFromDefaultDB('protos');
  287. }
  288. }),
  289. window._app.widgets.buttonStroked(
  290. {
  291. "label": 'Default World States',
  292. "onclick": function (e) {
  293. e.preventDefault();
  294. //page("/app/worlds/states")
  295. window.location.pathname = "/app/worlds/states"
  296. //_app.indexApp.getAppDetailsFromDefaultDB('states');
  297. }
  298. })
  299. ];
  300. var guiUser = [];
  301. if (_LCSDB.user().is) {
  302. guiUser = []
  303. }
  304. this.$components = [
  305. {
  306. $type: "h1",
  307. class: "mdc-typography--headline4",
  308. $text: "Worlds list"
  309. }
  310. ].concat(guiForAll).concat(guiUser)
  311. }
  312. }
  313. let luminaryFeature = {
  314. $cell: true,
  315. _luminarySwitch: null,
  316. $components: [
  317. {
  318. $type: "p",
  319. class: "mdc-typography--headline5",
  320. $text: "Use Krestianstvo Luminary (experimental)"
  321. },
  322. {
  323. $type: 'p'
  324. },
  325. _app.widgets.switch({
  326. 'id': 'forceLuminary',
  327. 'init': function () {
  328. this._switch = new mdc.switchControl.MDCSwitch(this);
  329. let config = localStorage.getItem('lcs_config');
  330. this._switch.checked = JSON.parse(config).luminary;
  331. // this._replaceSwitch = this._switch;
  332. },
  333. 'onchange': function (e) {
  334. if (this._switch) {
  335. let chkAttr = this._switch.checked;//this.getAttribute('checked');
  336. if (chkAttr) {
  337. let config = JSON.parse(localStorage.getItem('lcs_config'));
  338. config.luminary = true;
  339. localStorage.setItem('lcs_config', JSON.stringify(config));
  340. window.location.reload(true);
  341. //this._switch.checked = false;
  342. } else {
  343. let config = JSON.parse(localStorage.getItem('lcs_config'));
  344. config.luminary = false;
  345. localStorage.setItem('lcs_config', JSON.stringify(config));
  346. window.location.reload(true);
  347. }
  348. }
  349. }
  350. }
  351. ),
  352. {
  353. $type: 'label',
  354. for: 'input-forceLuminary',
  355. $text: 'On / Off'
  356. }
  357. ]
  358. }
  359. let userGUI =
  360. {
  361. $type: "div",
  362. id: "userGUI",
  363. // style:"background-color: #ffeb3b",
  364. class: "mdc-layout-grid mdc-layout-grid--align-left",
  365. _status: "",
  366. $init: function () {
  367. this._status = "Welcome!"
  368. },
  369. $update: function () {
  370. var gui = {};
  371. if (_LCSDB.user().is) {
  372. gui = [
  373. window._app.widgets.buttonRaised(
  374. {
  375. "label": 'Sign OUT',
  376. "onclick": function (e) {
  377. _LCSDB.user().leave();
  378. setTimeout(() =>
  379. {
  380. //window.sessionStorage.removeItem('alias');
  381. //window.sessionStorage.removeItem('tmp');
  382. window.location.reload(true);
  383. }, 1);
  384. }
  385. }),
  386. {
  387. $type: "p"
  388. },
  389. window._app.widgets.buttonStroked(
  390. {
  391. "label": 'PROFILE',
  392. "onclick": function (e) {
  393. e.preventDefault();
  394. //page("/profile")
  395. window.location.pathname = "/profile"
  396. }
  397. }),
  398. {
  399. $type: "p"
  400. },
  401. window._app.widgets.buttonStroked(
  402. {
  403. "label": 'My World protos',
  404. "onclick": function (e) {
  405. e.preventDefault();
  406. let alias = _LCSDB.user().is.alias;
  407. window.location.pathname = '/' + alias + '/worlds/protos'
  408. //page('/' + alias + '/worlds/protos');
  409. //_app.indexApp.getWorldsProtosFromUserDB(alias);
  410. }
  411. }),
  412. window._app.widgets.buttonStroked(
  413. {
  414. "label": 'My World states',
  415. "onclick": function (e) {
  416. e.preventDefault();
  417. let alias = _LCSDB.user().is.alias;
  418. window.location.pathname = '/' + alias + '/worlds/states'
  419. //page('/' + alias + '/worlds/states');
  420. // page.redirect('/' + alias + '/worlds/states');
  421. //_app.indexApp.getWorldsFromUserDB(alias);
  422. }
  423. })
  424. ]
  425. }
  426. this.$components = [luminaryFeature,
  427. _app.widgets.emptyDiv,
  428. window._app.widgets.buttonRaised(
  429. {
  430. "label": 'Connection settings',
  431. "onclick": function (e) {
  432. e.preventDefault();
  433. window.location.pathname = '/settings';
  434. }
  435. }), _app.widgets.emptyDiv,
  436. _app.widgets.divider,
  437. {
  438. $type: "h1",
  439. class: "mdc-typography--headline3",
  440. $text: this._status
  441. }
  442. ].concat(gui)
  443. }
  444. }
  445. let loginGUI =
  446. {
  447. $type: "div",
  448. id: "loginGUI",
  449. //style:"background-color: #efefef",
  450. class: "mdc-layout-grid mdc-layout-grid--align-left",
  451. _alias: null,
  452. _pass: null,
  453. _passField: null,
  454. _aliasField: null,
  455. _initData: function () {
  456. this._alias = '';
  457. this._pass = '';
  458. // if (window.sessionStorage.getItem('alias')) {
  459. // this._alias = window.sessionStorage.getItem('alias')
  460. // }
  461. // if (window.sessionStorage.getItem('tmp')) {
  462. // this._pass = window.sessionStorage.getItem('tmp')
  463. // }
  464. },
  465. $init: function () {
  466. this._initData();
  467. },
  468. $update: function () {
  469. this.$components = [
  470. {
  471. $type: "div",
  472. class: "mdc-layout-grid__inner",
  473. $components: [
  474. {
  475. $type: "div",
  476. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  477. $components: [
  478. {
  479. $type: "span",
  480. class: "mdc-typography--headline5",
  481. $text: "Login: "
  482. },
  483. window._app.widgets.inputTextFieldOutlined({
  484. "id": 'aliasInput',
  485. "label": "Login",
  486. "value": this._alias,
  487. "type": "text",
  488. "init": function () {
  489. this._aliasField = new mdc.textField.MDCTextField(this);
  490. }
  491. }),
  492. ]
  493. },
  494. {
  495. $type: "div",
  496. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  497. $components: [
  498. {
  499. $type: "span",
  500. class: "mdc-typography--headline5",
  501. $text: "Password: "
  502. },
  503. window._app.widgets.inputTextFieldOutlined({
  504. "id": 'passwordInput',
  505. "label": "Password",
  506. "value": this._pass,
  507. "type": "password",
  508. "init": function () {
  509. this._passField = new mdc.textField.MDCTextField(this);
  510. }
  511. }),
  512. ]
  513. },
  514. {
  515. $type: "div",
  516. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  517. $components: [
  518. window._app.widgets.buttonRaised(
  519. {
  520. "label": 'Sign UP',
  521. "onclick": function (e) {
  522. e.preventDefault();
  523. let alias = this._aliasField.value;
  524. let pass = this._passField.value
  525. if (pass.length < 7) {
  526. new Noty({
  527. text: "Your passphrase needs to be longer than 7 letters",
  528. timeout: 2000,
  529. theme: 'mint',
  530. layout: 'bottomRight',
  531. type: 'error'
  532. }).show();
  533. } else {
  534. //
  535. _LCSDB.user().create(alias, pass,
  536. function(ack) {
  537. if (!ack.wait) { }
  538. if (ack.err) {
  539. console.log(ack.err)
  540. return ack.err
  541. };
  542. if (ack.pub) {
  543. let userObj = {
  544. 'alias': alias,
  545. 'pub': ack.pub
  546. };
  547. _LCSDB.get('users').get(alias).put(userObj);
  548. }
  549. _LCSDB.user().auth(alias, pass);
  550. });
  551. }
  552. }
  553. }),
  554. {
  555. $type: "span",
  556. $text: " "
  557. },
  558. window._app.widgets.buttonRaised(
  559. {
  560. "label": 'Sign IN',
  561. "onclick": function (e) {
  562. e.preventDefault();
  563. _LCSDB.user().auth(this._aliasField.value, this._passField.value, function(ack) {
  564. if (ack.err) {
  565. new Noty({
  566. text: ack.err,
  567. timeout: 2000,
  568. theme: 'mint',
  569. layout: 'bottomRight',
  570. type: 'error'
  571. }).show();
  572. }
  573. });
  574. }
  575. })
  576. ]
  577. }
  578. ]
  579. }
  580. ]
  581. }
  582. }
  583. // document.querySelector("#userLobby").$cell({
  584. // id: "userLobby",
  585. // $cell: true,
  586. // $type: "div",
  587. // $components: [
  588. // userGUI, loginGUI, _app.widgets.divider, worldGUI]
  589. // }
  590. // );
  591. return [userGUI, loginGUI, _app.widgets.divider, worldGUI]
  592. }
  593. refresh() {
  594. // socket.emit('getWebAppUpdate', "");
  595. }
  596. parseOnlineData(data) {
  597. let parcedData = _app.parseAppInstancesData(data);
  598. //if (Object.entries(parcedData).length !== 0)
  599. let onlineGUIs = document.querySelectorAll('.online');
  600. onlineGUIs.forEach(function (item) {
  601. item._refresh(parcedData)
  602. });
  603. }
  604. createWorldCard(id, type) {
  605. let self = this;
  606. let onlineGUI = {
  607. $cell: true,
  608. id: "onlineGUI_" + id,
  609. class: "online",
  610. $type: "div",
  611. _instances: {},
  612. _worldListItem: function (m) {
  613. return {
  614. $type: "li",
  615. class: "mdc-list-item",
  616. $components: [
  617. {
  618. $type: "span",
  619. class: "world-link mdc-list-item__text",
  620. $components: [
  621. {
  622. $type: "span",
  623. class: "mdc-list-item__primary-text",
  624. $components: [
  625. {
  626. $type: "a",
  627. $text: m[0],
  628. //target: "_blank",
  629. // href: window.location.protocol + "//" + window.location.host + "/" + m[1].user + m[0],
  630. onclick: function (e) {
  631. self.checkForManualSettings();
  632. window.location.pathname = "/" + m[1].user + m[0];
  633. //self.refresh();
  634. }
  635. },
  636. ]
  637. },
  638. {
  639. $type: "span",
  640. class: "mdc-list-item__secondary-text",
  641. $text: _app.isLuminary ? _LangManager.language.t('users') + Object.keys(m[1].clients).length : _LangManager.language.t('users') + m[1].clients
  642. }
  643. ]
  644. }
  645. ]
  646. }
  647. },
  648. $components: [],
  649. _refresh: function (data) {
  650. if (data) {
  651. if (Object.entries(data).length !== 0) {
  652. if (this._worldInfo) {
  653. let insts = Object.entries(data).filter(el => el[0] == this._worldInfo.worldName);
  654. if (insts.length !== 0)
  655. this._instances = insts[0][1];
  656. }
  657. } else {
  658. this._instances = {}
  659. }
  660. }
  661. },
  662. $init: function () {
  663. if(_app.isLuminary){
  664. let luminaryPath = _app.luminaryPath;
  665. let ref = _LCSDB.get(luminaryPath);
  666. setInterval(function () {
  667. ref.get('allclients').once().map().once(res => {
  668. if (res) {
  669. if (res.id) {
  670. let clientTime = Gun.state.is(res, 'live');
  671. let now = Gun.time.is();
  672. if (now - clientTime < 10000) {
  673. let instance = res.user + res.instance;
  674. //let data = JSON.stringify({[res.instance]: {instance: instance, clients: {}, user: res.user, loadInfo: {}}});
  675. //console.log(data);
  676. if(!self.instances[res.instance]) {
  677. self.instances[res.instance] = {id: res.instance, instance: instance, clients: {[res.id]: res}, user: res.user, loadInfo: {} }
  678. } else {
  679. self.instances[res.instance].clients[res.id] = res
  680. }
  681. let data = JSON.stringify(self.instances);
  682. self.parseOnlineData(data);
  683. } else {
  684. if(self.instances[res.instance]){
  685. delete self.instances[res.instance].clients[res.id];
  686. if(Object.keys(self.instances[res.instance].clients).length == 0){
  687. delete self.instances[res.instance];
  688. self.parseOnlineData(JSON.stringify({}));
  689. }
  690. }
  691. //ref.get('instances').get(res.instance).get(res.id).put(null);
  692. }
  693. }
  694. }
  695. }
  696. )
  697. }, 5000);
  698. }
  699. this._refresh();
  700. },
  701. $update: function () {
  702. if (this._instances) {
  703. let cardListData = Object.entries(this._instances).filter(el => el[1].user == this._worldInfo.userAlias);
  704. this.$components = [
  705. {
  706. $type: "hr",
  707. class: "mdc-list-divider"
  708. }
  709. ].concat(cardListData.map(this._worldListItem))
  710. }
  711. }
  712. }
  713. return {
  714. $cell: true,
  715. id: 'worldCard_' + id,
  716. $type: "div",
  717. _worldInfo: {},
  718. _refresh: function (data) {
  719. this._worldInfo = data
  720. },
  721. // _getWorldInfo: async function () {
  722. // //get space for user
  723. // let info = await _app.getWorldInfo(user, space);
  724. // this._refresh(info);
  725. // },
  726. // _getStateInfo: async function () {
  727. // //get space for user
  728. // let info = await _app.getStateInfo(user, space, saveName);
  729. // this._refresh(info);
  730. // },
  731. $init: function () {
  732. //get space for user
  733. // if (!saveName) {
  734. // this._getWorldInfo();
  735. // } else {
  736. // this._getStateInfo();
  737. // }
  738. },
  739. $update: function () {
  740. //console.log(this._worldInfo);
  741. this.$components = [this._updateCard()]
  742. },
  743. $components: [],
  744. _updateCard: function () {
  745. let desc = this._worldInfo;
  746. if (!desc || Object.keys(desc).length == 0) {
  747. return {
  748. $type: "h1",
  749. class: "mdc-typography--headline4",
  750. $text: "ERROR: NO WORLD!"
  751. }
  752. }
  753. let userGUI = [];
  754. let online = [];
  755. let cardInfo = {
  756. "title": ""
  757. };
  758. if (type == "full") {
  759. } else {
  760. userGUI.push({
  761. $type: "a",
  762. class: "mdc-button mdc-button--compact mdc-card__action mdc-button--outlined",
  763. $text: "Details",
  764. onclick: function (e) {
  765. e.preventDefault();
  766. window.location.pathname = "/" + desc.userAlias + '/' + desc.worldName + '/about'
  767. }
  768. });
  769. }
  770. userGUI.push({
  771. $type: "a",
  772. class: "mdc-button mdc-button--raised mdc-card__action ",
  773. $text: _LangManager.language.t('start'),//"Start new",
  774. //target: "_blank",
  775. //href: "/" + desc.userAlias + '/' + desc.worldName,
  776. onclick: function (e) {
  777. self.checkForManualSettings();
  778. window.location.pathname = "/" + desc.userAlias + '/' + desc.worldName
  779. //self.refresh();
  780. }
  781. });
  782. if (desc.type == 'saveState') {
  783. cardInfo.title = desc.worldName.split('/')[2];
  784. }
  785. if (desc.type == 'proto') {
  786. cardInfo.title = desc.worldName;
  787. // userGUI.push(
  788. // {
  789. // $type: "a",
  790. // class: "mdc-button mdc-button--compact mdc-card__action",
  791. // $text: "States",
  792. // onclick: async function (e) {
  793. // e.preventDefault();
  794. // window.location.pathname = "/" + desc.userAlias + '/' + desc.worldName +'/about'
  795. // //console.log('clone');
  796. // // document.querySelector('#worldStatesGUI')._refresh({});
  797. // // let data = await _app.getSaveStates(desc.userAlias, desc.worldName);
  798. // // document.querySelector('#worldStatesGUI')._refresh(data);
  799. // }
  800. // }
  801. // )
  802. }
  803. online.push(onlineGUI);
  804. return {
  805. $cell: true,
  806. $type: "div",
  807. class: "mdc-card world-card",
  808. $components: [
  809. {
  810. $type: "section",
  811. class: "mdc-card__media world-card__16-9-media",
  812. $init: function () {
  813. if (desc.info.imgUrl !== "") {
  814. this.style.backgroundImage = 'linear-gradient(0deg, rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.3) ), url(' + desc.info.imgUrl + ')';
  815. }
  816. }
  817. },
  818. {
  819. $type: "section",
  820. class: "mdc-card__primary",
  821. $components: [
  822. {
  823. $type: "h1",
  824. class: "mdc-card__title mdc-card__title--large",
  825. $text: desc.info.title
  826. },
  827. {
  828. $type: "h2",
  829. class: "mdc-card__subtitle mdc-theme--text-secondary-on-background",
  830. $text: desc.info.text
  831. },
  832. {
  833. $type: "span",
  834. class: "mdc-card__subtitle mdc-theme--text-secondary-on-background",
  835. $text: 'id: '
  836. },
  837. {
  838. $type: "input",
  839. type: "text",
  840. disabled: "",
  841. style: "font-size:18px",
  842. value: cardInfo.title
  843. },
  844. {
  845. $type: "p",
  846. },
  847. {
  848. $type: "span",
  849. class: "mdc-card__subtitle mdc-theme--text-secondary-on-background",
  850. $text: 'created: ' + (new Date(desc.created)).toUTCString()
  851. },
  852. {
  853. $type: "p",
  854. }
  855. // ,{
  856. // $type: "span",
  857. // class: "mdc-card__subtitle mdc-theme--text-secondary-on-background",
  858. // $text: 'modified: ' + (new Date(desc[5])).toUTCString()
  859. // }
  860. ]
  861. },
  862. {
  863. $type: "section",
  864. class: "mdc-card__actions",
  865. $components: [
  866. ].concat(userGUI)
  867. },
  868. {
  869. $type: "section",
  870. class: "mdc-card__actions",
  871. $components: [
  872. {
  873. $type: 'div',
  874. $text: 'online now: '
  875. }
  876. ].concat(online)
  877. }
  878. ]
  879. }
  880. }
  881. }
  882. }
  883. createWorldsGUI(userAlias, worldName) {
  884. let self = this;
  885. let id = worldName ? worldName + '_' + userAlias : "allWorlds_" + userAlias
  886. let headerText = worldName ? 'States for ' + worldName : 'All Worlds Protos'
  887. let worldCards = {
  888. $cell: true,
  889. id: id,
  890. $type: "div",
  891. $components: [],
  892. _states: {},
  893. _refresh: function (data) {
  894. this._states = data
  895. },
  896. $init: async function () {
  897. //this._refresh();
  898. },
  899. _makeWorldCard: function (data) {
  900. let cardID = data[1].userAlias + '_' + data[1].worldName + '_' + data[0];
  901. let card = self.createWorldCard(cardID, 'min');
  902. card._worldInfo = data[1];
  903. card.$update();
  904. return {
  905. $cell: true,
  906. $type: "div",
  907. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-4",
  908. $components: [
  909. card
  910. //self.createWorldCard(data[1].userAlias, data[1].worldName, data[0])
  911. //this._worldCardDef(appInfo)
  912. ]
  913. }
  914. //console.log(data);
  915. },
  916. $update: function () {
  917. let cards = Object.entries(this._states)
  918. .filter(el => Object.keys(el[1]).length !== 0)
  919. .sort(function (el1, el2) {
  920. return parseInt(el2[1].created) - parseInt(el1[1].created)
  921. })
  922. .map(this._makeWorldCard);
  923. this.$components = [
  924. {
  925. $type: "div",
  926. class: "mdc-layout-grid",
  927. $components: [
  928. {
  929. $type: "div",
  930. class: "mdc-layout-grid__inner",
  931. $components: [
  932. {
  933. $type: "div",
  934. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  935. $components: [
  936. {
  937. $type: "H3",
  938. $text: headerText
  939. }
  940. ]
  941. }
  942. ]
  943. },
  944. {
  945. $type: "div",
  946. class: "mdc-layout-grid__inner",
  947. $components: cards
  948. }
  949. ]
  950. }
  951. ]
  952. }
  953. }
  954. return worldCards
  955. }
  956. checkForManualSettings() {
  957. console.log("check for manual settings");
  958. let manualSettings = localStorage.getItem('lcs_app_manual_settings');
  959. if(manualSettings){
  960. localStorage.removeItem('lcs_app_manual_settings');
  961. }
  962. let el = document.querySelector('#runWorldGUI');
  963. if (el) {
  964. if (el._arSwitch.checked){
  965. let arSettings = {
  966. model:{
  967. 'vwf/model/aframe': null
  968. },
  969. view:{
  970. 'vwf/view/aframe' : null,
  971. 'vwf/view/editor-new': null
  972. }
  973. }
  974. localStorage.setItem('lcs_app_manual_settings', JSON.stringify(arSettings));
  975. }
  976. if (el._turnArOnSwitch.checked){
  977. let arSettings = {
  978. model:{
  979. 'vwf/model/aframe': null
  980. },
  981. view:{
  982. 'vwf/view/aframe' : null,
  983. 'vwf/view/aframe-ar-driver': null
  984. }
  985. }
  986. localStorage.setItem('lcs_app_manual_settings', JSON.stringify(arSettings));
  987. }
  988. }
  989. }
  990. }
  991. export { IndexApp as default }
  992. //export {getAppDetails, generateFrontPage, setLanguage, initLocale};