index-app.js 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172
  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. let alias = this._aliasField.value;
  564. let pass = this._passField.value
  565. _app.helpers.authUser(alias, pass);
  566. // _LCSDB.user().auth.call(_LCSDB, alias, pass
  567. // // , function(ack) {
  568. // // if (ack.err) {
  569. // // new Noty({
  570. // // text: ack.err,
  571. // // timeout: 2000,
  572. // // theme: 'mint',
  573. // // layout: 'bottomRight',
  574. // // type: 'error'
  575. // // }).show();
  576. // // }
  577. // //}
  578. // );
  579. }
  580. })
  581. ]
  582. }
  583. ]
  584. }
  585. ]
  586. }
  587. }
  588. // document.querySelector("#userLobby").$cell({
  589. // id: "userLobby",
  590. // $cell: true,
  591. // $type: "div",
  592. // $components: [
  593. // userGUI, loginGUI, _app.widgets.divider, worldGUI]
  594. // }
  595. // );
  596. return [userGUI, loginGUI, _app.widgets.divider, worldGUI]
  597. }
  598. refresh() {
  599. // socket.emit('getWebAppUpdate', "");
  600. }
  601. parseOnlineData(data) {
  602. let parcedData = _app.parseAppInstancesData(data);
  603. //if (Object.entries(parcedData).length !== 0)
  604. let onlineGUIs = document.querySelectorAll('.online');
  605. onlineGUIs.forEach(function (item) {
  606. item._refresh(parcedData)
  607. });
  608. }
  609. createWorldCard(id, type) {
  610. let self = this;
  611. let onlineGUI = {
  612. $cell: true,
  613. id: "onlineGUI_" + id,
  614. class: "online",
  615. $type: "div",
  616. _instances: {},
  617. _worldListItem: function (m) {
  618. return {
  619. $type: "li",
  620. class: "mdc-list-item",
  621. $components: [
  622. {
  623. $type: "span",
  624. class: "world-link mdc-list-item__text",
  625. $components: [
  626. {
  627. $type: "span",
  628. class: "mdc-list-item__primary-text",
  629. $components: [
  630. {
  631. $type: "a",
  632. $text: m[0],
  633. //target: "_blank",
  634. // href: window.location.protocol + "//" + window.location.host + "/" + m[1].user + m[0],
  635. onclick: function (e) {
  636. self.checkForManualSettings();
  637. window.location.pathname = "/" + m[1].user + m[0];
  638. //self.refresh();
  639. }
  640. },
  641. ]
  642. },
  643. {
  644. $type: "span",
  645. class: "mdc-list-item__secondary-text",
  646. $text: _app.isLuminary ? _LangManager.language.t('users') + Object.keys(m[1].clients).length : _LangManager.language.t('users') + m[1].clients
  647. }
  648. ]
  649. }
  650. ]
  651. }
  652. },
  653. $components: [],
  654. _refresh: function (data) {
  655. if (data) {
  656. if (Object.entries(data).length !== 0) {
  657. if (this._worldInfo) {
  658. let insts = Object.entries(data).filter(el => el[0] == this._worldInfo.worldName);
  659. if (insts.length !== 0)
  660. this._instances = insts[0][1];
  661. }
  662. } else {
  663. this._instances = {}
  664. }
  665. }
  666. },
  667. $init: function () {
  668. if(_app.isLuminary){
  669. let luminaryPath = _app.luminaryPath;
  670. let ref = _LCSDB.get(luminaryPath);
  671. setInterval(function () {
  672. ref.get('allclients').once().map().once(res => {
  673. if (res) {
  674. if (res.id) {
  675. let clientTime = Gun.state.is(res, 'live');
  676. let now = Gun.time.is();
  677. if (now - clientTime < 10000) {
  678. let instance = res.user + res.instance;
  679. //let data = JSON.stringify({[res.instance]: {instance: instance, clients: {}, user: res.user, loadInfo: {}}});
  680. //console.log(data);
  681. if(!self.instances[res.instance]) {
  682. self.instances[res.instance] = {id: res.instance, instance: instance, clients: {[res.id]: res}, user: res.user, loadInfo: {} }
  683. } else {
  684. self.instances[res.instance].clients[res.id] = res
  685. }
  686. let data = JSON.stringify(self.instances);
  687. self.parseOnlineData(data);
  688. } else {
  689. if(self.instances[res.instance]){
  690. delete self.instances[res.instance].clients[res.id];
  691. if(Object.keys(self.instances[res.instance].clients).length == 0){
  692. delete self.instances[res.instance];
  693. self.parseOnlineData(JSON.stringify({}));
  694. }
  695. }
  696. //ref.get('instances').get(res.instance).get(res.id).put(null);
  697. }
  698. }
  699. }
  700. }
  701. )
  702. }, 5000);
  703. }
  704. this._refresh();
  705. },
  706. $update: function () {
  707. if (this._instances) {
  708. let cardListData = Object.entries(this._instances).filter(el => el[1].user == this._worldInfo.userAlias);
  709. this.$components = [
  710. {
  711. $type: "hr",
  712. class: "mdc-list-divider"
  713. }
  714. ].concat(cardListData.map(this._worldListItem))
  715. }
  716. }
  717. }
  718. return {
  719. $cell: true,
  720. id: 'worldCard_' + id,
  721. $type: "div",
  722. _worldInfo: {},
  723. _refresh: function (data) {
  724. this._worldInfo = data
  725. },
  726. // _getWorldInfo: async function () {
  727. // //get space for user
  728. // let info = await _app.getWorldInfo(user, space);
  729. // this._refresh(info);
  730. // },
  731. // _getStateInfo: async function () {
  732. // //get space for user
  733. // let info = await _app.getStateInfo(user, space, saveName);
  734. // this._refresh(info);
  735. // },
  736. $init: function () {
  737. //get space for user
  738. // if (!saveName) {
  739. // this._getWorldInfo();
  740. // } else {
  741. // this._getStateInfo();
  742. // }
  743. },
  744. $update: function () {
  745. //console.log(this._worldInfo);
  746. this.$components = [this._updateCard()]
  747. },
  748. $components: [],
  749. _updateCard: function () {
  750. let desc = this._worldInfo;
  751. if (!desc || Object.keys(desc).length == 0) {
  752. return {
  753. $type: "h1",
  754. class: "mdc-typography--headline4",
  755. $text: "ERROR: NO WORLD!"
  756. }
  757. }
  758. let userGUI = [];
  759. let online = [];
  760. let cardInfo = {
  761. "title": ""
  762. };
  763. if (type == "full") {
  764. } else {
  765. userGUI.push({
  766. $type: "a",
  767. class: "mdc-button mdc-button--compact mdc-card__action mdc-button--outlined",
  768. $text: "Details",
  769. onclick: function (e) {
  770. e.preventDefault();
  771. window.location.pathname = "/" + desc.userAlias + '/' + desc.worldName + '/about'
  772. }
  773. });
  774. }
  775. userGUI.push({
  776. $type: "a",
  777. class: "mdc-button mdc-button--raised mdc-card__action ",
  778. $text: _LangManager.language.t('start'),//"Start new",
  779. //target: "_blank",
  780. //href: "/" + desc.userAlias + '/' + desc.worldName,
  781. onclick: function (e) {
  782. self.checkForManualSettings();
  783. window.location.pathname = "/" + desc.userAlias + '/' + desc.worldName
  784. //self.refresh();
  785. }
  786. });
  787. if (desc.type == 'saveState') {
  788. cardInfo.title = desc.worldName.split('/')[2];
  789. }
  790. if (desc.type == 'proto') {
  791. cardInfo.title = desc.worldName;
  792. // userGUI.push(
  793. // {
  794. // $type: "a",
  795. // class: "mdc-button mdc-button--compact mdc-card__action",
  796. // $text: "States",
  797. // onclick: async function (e) {
  798. // e.preventDefault();
  799. // window.location.pathname = "/" + desc.userAlias + '/' + desc.worldName +'/about'
  800. // //console.log('clone');
  801. // // document.querySelector('#worldStatesGUI')._refresh({});
  802. // // let data = await _app.getSaveStates(desc.userAlias, desc.worldName);
  803. // // document.querySelector('#worldStatesGUI')._refresh(data);
  804. // }
  805. // }
  806. // )
  807. }
  808. online.push(onlineGUI);
  809. return {
  810. $cell: true,
  811. $type: "div",
  812. class: "mdc-card world-card",
  813. $components: [
  814. {
  815. $type: "section",
  816. class: "mdc-card__media world-card__16-9-media",
  817. $init: function () {
  818. if (desc.info.imgUrl !== "") {
  819. this.style.backgroundImage = 'linear-gradient(0deg, rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.3) ), url(' + desc.info.imgUrl + ')';
  820. }
  821. }
  822. },
  823. {
  824. $type: "section",
  825. class: "mdc-card__primary",
  826. $components: [
  827. {
  828. $type: "h1",
  829. class: "mdc-card__title mdc-card__title--large",
  830. $text: desc.info.title
  831. },
  832. {
  833. $type: "h2",
  834. class: "mdc-card__subtitle mdc-theme--text-secondary-on-background",
  835. $text: desc.info.text
  836. },
  837. {
  838. $type: "span",
  839. class: "mdc-card__subtitle mdc-theme--text-secondary-on-background",
  840. $text: 'id: '
  841. },
  842. {
  843. $type: "input",
  844. type: "text",
  845. disabled: "",
  846. style: "font-size:18px",
  847. value: cardInfo.title
  848. },
  849. {
  850. $type: "p",
  851. },
  852. {
  853. $type: "span",
  854. class: "mdc-card__subtitle mdc-theme--text-secondary-on-background",
  855. $text: 'created: ' + (new Date(desc.created)).toUTCString()
  856. },
  857. {
  858. $type: "p",
  859. }
  860. // ,{
  861. // $type: "span",
  862. // class: "mdc-card__subtitle mdc-theme--text-secondary-on-background",
  863. // $text: 'modified: ' + (new Date(desc[5])).toUTCString()
  864. // }
  865. ]
  866. },
  867. {
  868. $type: "section",
  869. class: "mdc-card__actions",
  870. $components: [
  871. ].concat(userGUI)
  872. },
  873. {
  874. $type: "section",
  875. class: "mdc-card__actions",
  876. $components: [
  877. {
  878. $type: 'div',
  879. $text: 'online now: '
  880. }
  881. ].concat(online)
  882. }
  883. ]
  884. }
  885. }
  886. }
  887. }
  888. createWorldsGUI(userAlias, worldName) {
  889. let self = this;
  890. let id = worldName ? worldName + '_' + userAlias : "allWorlds_" + userAlias
  891. let headerText = worldName ? 'States for ' + worldName : 'All Worlds Protos'
  892. let worldCards = {
  893. $cell: true,
  894. id: id,
  895. $type: "div",
  896. $components: [],
  897. _states: {},
  898. _refresh: function (data) {
  899. this._states = data
  900. },
  901. $init: async function () {
  902. //this._refresh();
  903. },
  904. _makeWorldCard: function (data) {
  905. let cardID = data[1].userAlias + '_' + data[1].worldName + '_' + data[0];
  906. let card = self.createWorldCard(cardID, 'min');
  907. card._worldInfo = data[1];
  908. card.$update();
  909. return {
  910. $cell: true,
  911. $type: "div",
  912. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-4",
  913. $components: [
  914. card
  915. //self.createWorldCard(data[1].userAlias, data[1].worldName, data[0])
  916. //this._worldCardDef(appInfo)
  917. ]
  918. }
  919. //console.log(data);
  920. },
  921. $update: function () {
  922. let cards = Object.entries(this._states)
  923. .filter(el => Object.keys(el[1]).length !== 0)
  924. .sort(function (el1, el2) {
  925. return parseInt(el2[1].created) - parseInt(el1[1].created)
  926. })
  927. .map(this._makeWorldCard);
  928. this.$components = [
  929. {
  930. $type: "div",
  931. class: "mdc-layout-grid",
  932. $components: [
  933. {
  934. $type: "div",
  935. class: "mdc-layout-grid__inner",
  936. $components: [
  937. {
  938. $type: "div",
  939. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  940. $components: [
  941. {
  942. $type: "H3",
  943. $text: headerText
  944. }
  945. ]
  946. }
  947. ]
  948. },
  949. {
  950. $type: "div",
  951. class: "mdc-layout-grid__inner",
  952. $components: cards
  953. }
  954. ]
  955. }
  956. ]
  957. }
  958. }
  959. return worldCards
  960. }
  961. checkForManualSettings() {
  962. console.log("check for manual settings");
  963. let manualSettings = localStorage.getItem('lcs_app_manual_settings');
  964. if(manualSettings){
  965. localStorage.removeItem('lcs_app_manual_settings');
  966. }
  967. let el = document.querySelector('#runWorldGUI');
  968. if (el) {
  969. if (el._arSwitch.checked){
  970. let arSettings = {
  971. model:{
  972. 'vwf/model/aframe': null
  973. },
  974. view:{
  975. 'vwf/view/aframe' : null,
  976. 'vwf/view/editor-new': null
  977. }
  978. }
  979. localStorage.setItem('lcs_app_manual_settings', JSON.stringify(arSettings));
  980. }
  981. if (el._turnArOnSwitch.checked){
  982. let arSettings = {
  983. model:{
  984. 'vwf/model/aframe': null
  985. },
  986. view:{
  987. 'vwf/view/aframe' : null,
  988. 'vwf/view/aframe-ar-driver': null
  989. }
  990. }
  991. localStorage.setItem('lcs_app_manual_settings', JSON.stringify(arSettings));
  992. }
  993. }
  994. }
  995. }
  996. export { IndexApp as default }
  997. //export {getAppDetails, generateFrontPage, setLanguage, initLocale};