Browse Source

Merge remote-tracking branch 'upstream/lcs2New'

Nikolay Suslov 5 years ago
parent
commit
f46f4a95c7

+ 75 - 17
public/app.js

@@ -162,9 +162,14 @@ class App {
         let responseText = await proxyFile.text();
 
         if (responseText) {
+
+          let created = new Date().valueOf();
+
           let obj = {
             //'owner': userPub,
-            'file': responseText
+            'file': responseText,
+            'modified': created,
+            'created': created
           }
           proxyObj[entryName] = obj;
         }
@@ -178,7 +183,7 @@ class App {
 
   }
 
-  async loadWorldsDefaults() {
+  async loadWorldsDefaults(replace) {
 
    //load to DB default worlds
 
@@ -203,11 +208,13 @@ class App {
         let worldFile = await fetch(url, { method: 'get' });
         let worldSource = await worldFile.text();
         if (worldSource) {
-          let modified = new Date().valueOf();
+          //let modified = new Date().valueOf();
+          let created = new Date().valueOf();
 
           let obj = {
             'file': worldSource,
-            'modified': modified
+            'modified': created,
+            'created': created
 
           }
 
@@ -229,6 +236,8 @@ class App {
 
     console.log(worldsObj);
 
+    if(replace){
+
     Object.entries(worldsObj).forEach(el => {
 
       let worldName = el[0];
@@ -239,6 +248,24 @@ class App {
 
       })
     })
+  } else {
+    //force replace all default worlds
+
+      Object.entries(worldsObj).forEach(el => {
+
+        let worldName = el[0];
+        let files = el[1];
+        Object.entries(files).forEach(file => {
+  
+          _LCSDB.user().get('worlds').get(worldName).get(file[0]).not(res=>{
+            _LCSDB.user().get('worlds').get(worldName).get(file[0]).put(file[1]);
+          })
+  
+        })
+      })
+
+    }
+
   }
 
   async loadEmptyDefaultProto() {
@@ -266,11 +293,11 @@ class App {
           "vwf/view/editor-new": null
         } 
       }, 4),
-
+      "assets_json": JSON.stringify ({}),
       "index_vwf_html": JSON.stringify ("<!-- DEFAULT HTML -->"),
       "appui_js": JSON.stringify ("//appui in JS"),
-      "info_json": JSON.stringify ({
-        "info": {
+      "info_json": JSON.stringify ({ 
+        "info": { 
           "en": {
               "title": "Empty World",
               "imgUrl": "",
@@ -282,7 +309,7 @@ class App {
               "text": "Новый Мир"
           }
       }
-      })
+      }, null, 4)
     }
 
     worldsObj['empty'] = {
@@ -293,10 +320,12 @@ class App {
     }
 
     Object.keys(emptyWorld).forEach(el=>{
-      let modified = new Date().valueOf();
+      //let modified = new Date().valueOf();
+      let created = new Date().valueOf();
       let obj = {
         'file': emptyWorld[el],
-        'modified': modified
+        'modified': created,
+        'created': created
       }
       worldsObj['empty'][el] = obj;
     }) 
@@ -402,6 +431,7 @@ class App {
 
             let loadDefaults = {
               $cell: true,
+              _replaceSwitch: null,
               $components: [
                 {
                   $type: "p",
@@ -415,9 +445,29 @@ class App {
                   $text: "Load default worlds (from server)",
                   onclick: function (e) {
                     console.log("admin action");
-                    window._app.loadWorldsDefaults();
+                    let forceReplace = this._replaceSwitch.checked;
+                    //console.log(forceReplace);
+                    window._app.loadWorldsDefaults(forceReplace);
                   }
-                }
+                },
+                {
+                  $type: 'p'
+                },
+                _cellWidgets.switch({
+                  'id': 'forceReplace',
+                  'init': function () {
+                      this._switch = new mdc.switchControl.MDCSwitch(this);
+                      this._replaceSwitch = this._switch;
+                      this._switch.checked = false;
+                  }
+              }
+              ),
+              {
+                $type: 'label',
+                for: 'input-forceReplace',
+                $text: 'Force replace'
+              }
+
               ]
             }
 
@@ -961,8 +1011,7 @@ class App {
   async getProtoWorldFiles(userPub, worldName, date) {
 
     let fileNamesAll = await _LCSDB.user(userPub).get('worlds').get(worldName).once().then();
-    let worldFileNames = Object.keys(fileNamesAll).filter(el => (el !== '_') && (el !== 'owner') && (el !== 'parent')
-      && (el !== 'info_json'));
+    let worldFileNames = Object.keys(fileNamesAll).filter(el => (el !== '_') && (el !== 'owner') && (el !== 'parent') && (el !== 'featured') && (el !== 'published') && (el !== 'info_json'));
 
     let worldObj = {};
     for (var el in worldFileNames) {
@@ -970,7 +1019,8 @@ class App {
       let res = await _LCSDB.user(userPub).get('worlds').get(worldName).get(fn).once().then();
       var data = {
         'file': res.file,
-        'modified': res.modified
+        'modified': res.modified,
+        'created': res.created
       }
       if (!date) {
         data = {
@@ -1173,7 +1223,7 @@ class App {
 
       if (res) {
 
-        let modified = new Date().valueOf();
+        let modified = saveRevision;
         let newOwner = _LCSUSER.is.pub;
         let userName = _LCSUSER.is.alias;
 
@@ -1181,7 +1231,8 @@ class App {
           'parent': userName + '/' + root,
           'owner': newOwner,
           'file': res.file,
-          'modified': modified
+          //'modified': modified,
+          'created': modified
 
         }
 
@@ -1190,6 +1241,13 @@ class App {
         _LCSUSER.get('documents').get(root).get(docInfoName).not(res => {
           _LCSUSER.get('documents').get(root).get(docInfoName).put(obj);
         });
+
+        _LCSUSER.get('documents').get(root).get(docInfoName).get('created').not(res => {
+          _LCSUSER.get('documents').get(root).get(docInfoName).get('created').put(modified);
+        });
+
+        _LCSUSER.get('documents').get(root).get(docInfoName).get('modified').put(modified);
+
       }
     });
 

+ 15 - 0
public/defaults/worlds/gearvr/appui.js

@@ -0,0 +1,15 @@
+//-----App ui-----
+
+function createApp() {
+    
+        let self = this
+    
+        return {
+            $cell: true,
+            $type: "div",
+            class: "propGrid max-width mdc-layout-grid mdc-layout-grid--align-left",
+            $components: []
+        }
+
+    }
+    

+ 14 - 0
public/defaults/worlds/gearvr/assets.json

@@ -0,0 +1,14 @@
+{
+    "bg":{
+        "tag": "img",
+        "src": "/defaults/assets/bg.jpg"
+    },
+    "sky":{
+        "tag": "img",
+        "src": "/defaults/assets/skyes/sky3.jpg"
+    },
+     "bg2":{
+        "tag": "img",
+        "src": "/defaults/assets/checker.jpg"
+    }
+}

+ 8 - 0
public/defaults/worlds/gearvr/index.vwf.config.yaml

@@ -0,0 +1,8 @@
+---
+info:
+  title: "GearVR Example App"
+model:
+  vwf/model/aframe:
+view:
+  vwf/view/aframe: {gearvr: true, wmrleft: true, wmrright: true}
+  vwf/view/editor-new:

+ 52 - 0
public/defaults/worlds/gearvr/index.vwf.yaml

@@ -0,0 +1,52 @@
+# A-Frame & VWF simple scene
+# Copyright 2017 Krestianstvo.org project
+---
+extends: http://vwf.example.com/aframe/ascene.vwf
+properties:
+  fog: "type: linear; color: #ECECEC; far: 20; near: 0"
+  assets: "assets.json"
+children:
+  myLight:
+    extends: http://vwf.example.com/aframe/alight.vwf
+    properties:
+      type: "point"
+      color: "white"
+      position: "0 10 5"
+      rotation: "0 0 0"
+  groundPlane:
+    extends: http://vwf.example.com/aframe/aplane.vwf
+    properties:
+        height: 50
+        width: 50
+        rotation: [-90, 0, 0]
+    children:    
+      material:
+        extends: http://vwf.example.com/aframe/aMaterialComponent.vwf
+        properties:
+          wireframe: false
+          src: "#bg2"
+          repeat: "10 10"
+  spaceText:
+    extends: http://vwf.example.com/aframe/atext.vwf
+    properties:
+      value: "Virtual World Framework & VR Controllers"
+      color: "#2b5d83"
+      position: [-2, 2.5, -3]
+  cube:
+    extends: http://vwf.example.com/aframe/abox.vwf
+    properties:
+      position: "0 1 -3"
+      rotation: "0 0 0"
+      depth: 1
+      height: 1
+      width: 1
+    children:    
+      material:
+        extends: http://vwf.example.com/aframe/aMaterialComponent.vwf
+        properties:
+          color: "#3c7249"
+  newSky:
+    extends: http://vwf.example.com/aframe/aentity.vwf
+    children:
+      skyshader:
+        extends: http://vwf.example.com/aframe/app-skyshader-component.vwf

+ 14 - 0
public/defaults/worlds/gearvr/info.json

@@ -0,0 +1,14 @@
+{
+    "info": {
+        "en": {
+            "title": "Control in VR app",
+            "imgUrl": "/defaults/worlds/gearvr/webimg.jpg",
+            "text": "VR controler example"
+        },
+        "ru": {
+            "title": "Контроллер в VR",
+            "imgUrl": "/defaults/worlds/gearvr/webimg.jpg",
+            "text": "Пример мира с упралением контроллером GearVR"
+        }
+    }
+}

BIN
public/defaults/worlds/gearvr/webimg.jpg


+ 57 - 0
public/defaults/worlds/multipixel/appui.js

@@ -0,0 +1,57 @@
+
+function createApp() {
+
+    let self = this
+
+  function createCameraButton(camNum) {
+
+        let label = "Camera " + camNum;
+        let camID = "/multicam/camera"+ camNum + "/cam";
+        let camOffsetID = "/multicam/camera"+ camNum + "/cam/viewoffset";
+
+      return {
+        $cell: true,
+        $type: "button",
+        class: "mdc-button mdc-button--raised",
+        $text: label,
+        onclick: function (e) {
+            let nodeID = vwf.find("",camID)[0];
+            let offsetCompID =  vwf.find("",camOffsetID)[0];
+            let avatarID = vwf.moniker_;
+            vwf_view.kernel.callMethod(offsetCompID, "setParams", []);
+            vwf_view.kernel.callMethod(nodeID, "setCameraToActive", [avatarID]);
+        }
+    }
+
+    }
+
+
+    return {
+        $cell: true,
+        $type: "div",
+        class: "propGrid max-width mdc-layout-grid mdc-layout-grid--align-left",
+        $components: [
+            {
+                $cell: true,
+                $type: "div",
+                class: "mdc-layout-grid__inner",
+                $components: [
+                    {
+                        $cell: true,
+                        $type: "div",
+                        class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
+                        $components: [
+                          
+                            createCameraButton("1"),
+                            createCameraButton("2")
+
+
+                        ]
+                    }
+
+
+                ]
+            }
+        ]
+    }
+}

+ 18 - 0
public/defaults/worlds/multipixel/assets.json

@@ -0,0 +1,18 @@
+{
+    "bg2":{
+        "tag": "img",
+        "src": "/defaults/assets/checker.jpg"
+    },
+    "sky":{
+        "tag": "img",
+        "src": "/defaults/assets/skyes/sky3.jpg"
+    },
+    "nwtree-obj":{
+        "tag": "a-asset-item",
+        "src": "/defaults/assets/models/nwtree/model.obj"
+    },
+    "nwtree-mtl":{
+        "tag": "a-asset-item",
+        "src": "/defaults/assets/models/nwtree/materials.mtl"
+    }
+}

+ 8 - 0
public/defaults/worlds/multipixel/index.vwf.config.yaml

@@ -0,0 +1,8 @@
+---
+info:
+  title: "VWF & AFrame Example App"
+model:
+  vwf/model/aframe:
+view:
+  vwf/view/aframe:
+  vwf/view/editor-new:

+ 155 - 0
public/defaults/worlds/multipixel/index.vwf.yaml

@@ -0,0 +1,155 @@
+# A-Frame & VWF simple scene
+# Copyright 2017 Krestianstvo.org project
+# Christmas tree model by 14islands Lab Made with Blocks Public / Remixable (CC-BY) https://poly.google.com/view/2VSoAQN6JoH
+---
+extends: http://vwf.example.com/aframe/ascene.vwf
+properties:
+  transparent: true
+  assets: "assets.json"
+children:
+  sky:
+    extends: http://vwf.example.com/aframe/asky.vwf
+    properties:
+    children:
+      material:
+        extends: http://vwf.example.com/aframe/aMaterialComponent.vwf
+        properties:
+          color: "#ECECEC"
+          side: "back"
+          fog: false
+  myLightSG:
+    extends: http://vwf.example.com/aframe/alight.vwf
+    properties:
+      type: "directional"
+      color: "white"
+      position: "6 22 6"
+      rotation: "-77 85 64"
+  myLightSB:
+    extends: http://vwf.example.com/aframe/alight.vwf
+    properties:
+      type: "spot"
+      color: "blue"
+      position: "0 5 -25"
+      rotation: "0 0 150"
+  myLightSR:
+    extends: http://vwf.example.com/aframe/alight.vwf
+    properties:
+      type: "spot"
+      color: "red"
+      position: "0 5 -25"
+      rotation: "0 -3 150"
+  model:
+    extends: http://vwf.example.com/aframe/aobjmodel.vwf
+    properties:
+      src: "#nwtree-obj"
+      mtl: "#nwtree-mtl"
+      position: "-1 6 -25"
+      rotation: "0 -45 0"
+      scale: "20 20 20"
+    children:
+      interpolation:
+        extends: http://vwf.example.com/aframe/interpolation-component.vwf
+        properties:
+          enabled: true
+    methods:
+          run:
+            body: |
+              var time = vwf.now;
+              let rot = AFRAME.utils.coordinates.parse(this.rotation);
+              this.rotation = [rot.x, Math.sin(time)*50, rot.z];
+              this.future( 0.01 ).run();  // schedule the next step
+  spaceText:
+    extends: http://vwf.example.com/aframe/atext.vwf
+    properties:
+      value: "Happy New Year 2018!"
+      color: "#d5ebda"
+      position: "-19 5 -30"
+      rotation: "0 0 45"
+      scale: "9 9 9"
+  spaceText2:
+    extends: http://vwf.example.com/aframe/atext.vwf
+    properties:
+      value: "Project by Krestianstvo.org"
+      color: "#305b32"
+      position: "5 10 -30"
+      scale: "5 5 5"
+  box:
+    extends: http://vwf.example.com/aframe/abox.vwf
+    properties:
+      position: "10 0.5 0"
+      rotation: "0 -30 0"
+      depth: 2
+      height: 5
+      width: 2
+    children:
+      material:
+        extends: http://vwf.example.com/aframe/aMaterialComponent.vwf
+        properties:
+          color: "#3c7249"
+  sphere:
+    extends: http://vwf.example.com/aframe/asphere.vwf
+    properties:
+      position: "7 15 -25"
+      radius: 5
+    children:
+      material:
+        extends: http://vwf.example.com/aframe/aMaterialComponent.vwf
+        properties:
+          color: "#e0e014"
+          wireframe: true
+  box2:
+    extends: http://vwf.example.com/aframe/abox.vwf
+    properties:
+      position: "0 0 -35"
+      rotation: "0 0 0"
+      depth: 1
+      height: 50
+      width: 50
+    children:
+      material:
+        extends: http://vwf.example.com/aframe/aMaterialComponent.vwf
+        properties:
+          color: "white"
+  groundPlane:
+    extends: http://vwf.example.com/aframe/aplane.vwf
+    properties:
+      height: 100
+      width: 100
+      rotation: "-90 0 0"
+    children:
+      material:
+        extends: http://vwf.example.com/aframe/aMaterialComponent.vwf
+        properties:
+          color: "white"
+          wireframe: false
+          src: "#bg2"
+          repeat: "10 10"
+  multicam:
+      extends: http://vwf.example.com/aframe/abox.vwf
+      properties:
+        position: "0 4 -2"
+        rotation: "0 0 0"
+        depth: 0.5
+        height: 0.5
+        width: 0.5
+      children:
+        material:
+          extends: http://vwf.example.com/aframe/aMaterialComponent.vwf
+          properties:
+            opacity: 0.5
+            transparent: true
+            color: "green"
+        interpolation:
+          extends: http://vwf.example.com/aframe/interpolation-component.vwf
+          properties:
+            enabled: true
+        camera1:
+          extends: http://vwf.example.com/aframe/offsetcamera.vwf
+        camera2:
+          extends: http://vwf.example.com/aframe/offsetcamera.vwf
+methods:
+  initialize:
+    body: |
+          console.log("initializing...");
+          this.children.multicam.camera1.createCamera(3000, 2000, 0, 0, 1500, 2000);
+          this.children.multicam.camera2.createCamera(3000, 2000, 1500, 0, 1500, 2000);

+ 14 - 0
public/defaults/worlds/multipixel/info.json

@@ -0,0 +1,14 @@
+{
+    "info": {
+        "en": {
+            "title": "Multi-Pixel",
+            "imgUrl": "/defaults/worlds/multipixel/webimg.jpg",
+            "text": "Multi offset view camera example"
+        },
+        "ru": {
+            "title": "Мульти-пиксел",
+            "imgUrl": "/defaults/worlds/multipixel/webimg.jpg",
+            "text": "Пример мира с мульти-пекселом"
+        }
+    }
+}

BIN
public/defaults/worlds/multipixel/webimg.jpg


+ 72 - 0
public/defaults/worlds/webrtc/appui.js

@@ -0,0 +1,72 @@
+//-----App ui-----
+
+function createApp() {
+    
+        let self = this
+    
+    
+    
+        function makeSetter(val) {
+            let setstr = 'this.' + val + '= value; this.redrawEvent();'
+            return setstr
+        }
+    
+        function getNewPosition() {
+            //let allChild = vwf.find("","/*")
+            let cursorVisID = vwf.find("myCursor-avatar-" + vwf.moniker_, "./vis")[0]
+            let avPos = AFRAME.utils.coordinates.parse(vwf.callMethod(cursorVisID, 'worldPosition'));
+            let newPos = [avPos.x, avPos.y, avPos.z]
+            return newPos
+        }
+    
+        return {
+            $cell: true,
+            $type: "div",
+            class: "propGrid max-width mdc-layout-grid mdc-layout-grid--align-left",
+            $components: [
+                {
+                    $cell: true,
+                    $type: "div",
+                    class: "mdc-layout-grid__inner",
+                    $components: [
+                        {
+                            $cell: true,
+                            $type: "div",
+                            class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
+                            $components: [
+                        
+                                {
+                                    $cell: true,
+                                    $type: "button",
+                                    class: "mdc-button mdc-button--raised",
+                                    $text: "Wide",
+                                    onclick: function (e) {
+                                        let avatarID = 'avatar-'+vwf.moniker_;
+                                        vwf_view.kernel.callMethod(avatarID, "setBigVideoHead", []);
+                                       
+                                    }
+    
+                                },
+                                {
+                                    $cell: true,
+                                    $type: "button",
+                                    class: "mdc-button mdc-button--raised",
+                                    $text: "Small",
+                                    onclick: function (e) {
+                                        let avatarID = 'avatar-'+vwf.moniker_;
+                                        vwf_view.kernel.callMethod(avatarID, "setSmallVideoHead", []);
+                                       
+                                    }
+    
+                                }
+    
+    
+                            ]
+                        }
+
+                    ]
+                }
+            ]
+        }
+    }
+    

+ 10 - 0
public/defaults/worlds/webrtc/assets.json

@@ -0,0 +1,10 @@
+{
+    "sky":{
+        "tag": "img",
+        "src": "/defaults/assets/skyes/sky3.jpg"
+    },
+     "bg2":{
+        "tag": "img",
+        "src": "/defaults/assets/checker.jpg"
+    }
+}

+ 9 - 0
public/defaults/worlds/webrtc/index.vwf.config.yaml

@@ -0,0 +1,9 @@
+---
+info:
+  title: "VWF & AFrame Example App"
+model:
+  vwf/model/aframe:
+view:
+  vwf/view/aframe:
+  vwf/view/editor-new:
+  vwf/view/webrtc:

+ 65 - 0
public/defaults/worlds/webrtc/index.vwf.yaml

@@ -0,0 +1,65 @@
+# A-Frame & VWF simple scene
+# Copyright 2017 Krestianstvo.org project
+---
+extends: http://vwf.example.com/aframe/ascene.vwf
+properties:
+  assets: "assets.json"
+children:
+  fog:
+    extends: http://vwf.example.com/aframe/aSceneFogComponent.vwf
+    type: "component"
+    properties:
+      fogType: "linear"
+      fogColor: "#ECECEC"
+      far: 20
+      near: 0
+  groundPlane:
+    extends: http://vwf.example.com/aframe/aplane.vwf
+    properties:
+      height: 50
+      width: 50
+      rotation: "-90 0 0"
+    children:
+      material:
+        extends: http://vwf.example.com/aframe/aMaterialComponent.vwf
+        properties:
+          wireframe: false
+          src: "#bg2"
+          repeat: "10 10"
+  myLight:
+    extends: http://vwf.example.com/aframe/alight.vwf
+    properties:
+      type: "hemisphere"
+      color: "white"
+      position: "0 10 5"
+      rotation: "0 0 0"
+  sky:
+    extends: http://vwf.example.com/aframe/asky.vwf
+    properties:
+    children:
+      material:
+        extends: http://vwf.example.com/aframe/aMaterialComponent.vwf
+        properties:
+          color: "#ECECEC"
+          src: "#sky"
+          fog: false
+          side: "back"
+  spaceText:
+    extends: http://vwf.example.com/aframe/atext.vwf
+    properties:
+      value: "WebRTC app"
+      color: "white"
+      position: "-2 2.5 -2"
+  box:
+    extends: http://vwf.example.com/aframe/abox.vwf
+    properties:
+      position: "0 0 -3"
+      rotation: "0 0 0"
+      depth: 3
+      height: 0.2
+      width: 3
+    children:
+      material:
+        extends: http://vwf.example.com/aframe/aMaterialComponent.vwf
+        properties:
+          color: "#3c7249"

+ 14 - 0
public/defaults/worlds/webrtc/info.json

@@ -0,0 +1,14 @@
+{
+    "info": {
+        "en": {
+            "title": "WebRTC app",
+            "imgUrl": "/defaults/worlds/webrtc/webimg.jpg",
+            "text": "Audio and video streaming for Avatars"
+        },
+        "ru": {
+            "title": "WebRTC приложение",
+            "imgUrl": "/defaults/worlds/webrtc/webimg.jpg",
+            "text": "Пример приложения с использованием WebRTC потокового аудио и видео"
+        }
+    }
+}

BIN
public/defaults/worlds/webrtc/webimg.jpg


+ 1 - 1
public/lib/widgets.js

@@ -591,7 +591,7 @@
                                         $type: "input",
                                         type: "checkbox",
                                         class: "mdc-switch__native-control",
-                                        
+                                        id: 'input-' + obj.id,
                                         //$init: obj.init,
                                         //id: "basic-switch",
                                         onchange: obj.onchange,

+ 31 - 3
public/web/index-app.js

@@ -516,7 +516,7 @@ class IndexApp {
                 var appInfo = m
                 if (langID) {
                     if (m[1][langID]) {
-                        appInfo = [m[0], m[1][langID], m[1].user, m[1].type]
+                        appInfo = [m[0], m[1][langID], m[1].user, m[1].type, m[1].created, m[1].modified]
                     }
                 }
                 return {
@@ -554,7 +554,9 @@ class IndexApp {
                             {
                                 $type: "div",
                                 class: "mdc-layout-grid__inner",
-                                $components: Object.entries(this._jsonData).map(this._makeWorldCard)
+                                $components: Object.entries(this._jsonData).sort(function(el1, el2){
+                                    return parseInt(el2[1].created) - parseInt(el1[1].created)
+                                }).map(this._makeWorldCard)
                             }
                         ]
 
@@ -680,8 +682,21 @@ class IndexApp {
                                 {
                                     $type: "h2",
                                     class: "mdc-card__subtitle mdc-theme--text-secondary-on-background",
-                                    $text: desc[1].text
+                                    $text: desc[1].text 
+                                },
+                                {
+                                    $type: "span",
+                                    class: "mdc-card__subtitle mdc-theme--text-secondary-on-background",
+                                    $text: 'created: ' + (new Date(desc[4])).toUTCString()
+                                },
+                                {
+                                    $type: "p", 
                                 }
+                                // ,{
+                                //     $type: "span",
+                                //     class: "mdc-card__subtitle mdc-theme--text-secondary-on-background",
+                                //     $text: 'modified: ' + (new Date(desc[5])).toUTCString()
+                                // }
                             ]
                         },
                         {
@@ -814,11 +829,15 @@ class IndexApp {
                     saves.forEach(el => {
                         db.get('documents').get(index).get(el).once(res => {
                             if (res) {
+                                let created = res.created ? res.created: res.modified;
+
                                 let fileName = el.split('/')[2].replace('_info_vwf_json', "");
                                 let world = JSON.parse(res.file);
                                 let root = Object.keys(world)[0];
                                 world[root].user = userAlias;
                                 world[root].type = 'saveState';
+                                world[root].created = created;
+                                world[root].modified = res.modified;
                                 this.worlds[index + '/load/' + fileName] = world[root];
                                 document.querySelector("#main")._jsonData = Object.assign({}, this.worlds);
                             }
@@ -861,10 +880,14 @@ class IndexApp {
 
                         if (res) {
 
+                            let created = res.created ? res.created: res.modified;
+
                             let world = JSON.parse(res.file);
                             let root = Object.keys(world)[0];
                             world[root].user = userAlias;
                             world[root].type = 'proto';
+                            world[root].created = created;
+                            world[root].modified = res.modified;
                             this.worlds[index] = world[root];
                             document.querySelector("#main")._jsonData = Object.assign({}, this.worlds);
                         }
@@ -920,11 +943,16 @@ class IndexApp {
                                     db.get('documents').get(index).get(el).once(res => {
 
                                         if (res) {
+
+                                            let created = res.created ? res.created: res.modified;
+
                                             let fileName = el.split('/')[2].replace('_info_vwf_json', "");
                                             let world = JSON.parse(res.file);
                                             let root = Object.keys(world)[0];
                                             world[root].user = userAlias;
                                             world[root].type = 'saveState';
+                                            world[root].created = created;
+                                            world[root].modified = res.modified;
                                             this.worlds[index + '/load/' + fileName] = world[root];
                                             document.querySelector("#main")._jsonData = Object.assign({}, this.worlds);