index-app.js 44 KB

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