index-app.js 44 KB

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