Browse Source

use query ?k=instanceID instead url path

Nikolay Suslov 4 years ago
parent
commit
e3e3f0f81b
5 changed files with 345 additions and 15 deletions
  1. 52 7
      public/core/app.js
  2. 1 0
      public/index.js
  3. 260 0
      public/lib/page-query.js
  4. 30 6
      public/lib/page.mjs
  5. 2 2
      public/web/index-app.js

+ 52 - 7
public/core/app.js

@@ -69,6 +69,7 @@ class App {
 
 
   setPageRoutes() {
   setPageRoutes() {
     //client routes
     //client routes
+    page('*', this.HandleQuery);
     page('/', this.HandleIndex);
     page('/', this.HandleIndex);
     page('/setup', this.HandleSetupIndex);
     page('/setup', this.HandleSetupIndex);
     page('/debug', this.HandleDebugIndex);
     page('/debug', this.HandleDebugIndex);
@@ -77,10 +78,11 @@ class App {
     page('/worlds', this.HandleIndex);
     page('/worlds', this.HandleIndex);
     page('/:user/worlds', this.HandleUserWorlds);
     page('/:user/worlds', this.HandleUserWorlds);
     page('/:user/:type/:name/edit/:file', this.HandleFileEdit);
     page('/:user/:type/:name/edit/:file', this.HandleFileEdit);
-    page('/:user/:space', this.HandleParsableRequestGenID);
+    page('/:user/:space', this.HandleParsableRequestWithID);
+    page('/:user/:space/index.vwf', this.HandleParsableRequestWithID);
     page('/:user/:space/about', this.HandleWorldAbout);
     page('/:user/:space/about', this.HandleWorldAbout);
-    page('/:user/:space/:id', this.HandleParsableRequestWithID);
-    page('/:user/:space/index.vwf/:id', this.HandleParsableRequestWithID);
+    //page('/:user/:space/:id', this.HandleParsableRequestWithID);
+    //page('/:user/:space/index.vwf/:id', this.HandleParsableRequestWithID);
     page('/:user/:space/load/:savename', this.HandleParsableLoadRequest);
     page('/:user/:space/load/:savename', this.HandleParsableLoadRequest);
     page('/:user/:space/:id/load/:savename', this.HandleParsableRequestWithID);
     page('/:user/:space/:id/load/:savename', this.HandleParsableRequestWithID);
     page('/:user/:space/index.vwf/:id/load/:savename', this.HandleParsableRequestWithID);
     page('/:user/:space/index.vwf/:id/load/:savename', this.HandleParsableRequestWithID);
@@ -1274,6 +1276,13 @@ class App {
     return p
     return p
   }
   }
 
 
+  ////////HANDLERS//////
+
+  HandleQuery(ctx, next) {
+    ctx.query = qs.parse(location.search.slice(1));
+    next();
+  }
+
   HandleIndex() {
   HandleIndex() {
 
 
     console.log("INDEX");
     console.log("INDEX");
@@ -1292,7 +1301,15 @@ class App {
 
 
   HandleNoPage() {
   HandleNoPage() {
 
 
-    console.log("no such page")
+    console.log("no such page");
+    _app.hideProgressBar();
+
+    let t404 = `
+    <h1>404 no page...</h1>
+    `; 
+    let el = document.getElementById("loadscreen");
+    el.innerHTML = t404;
+
   }
   }
 
 
   //handle parcable requests
   //handle parcable requests
@@ -1368,6 +1385,11 @@ class App {
 
 
   }
   }
 
 
+  generateInstanceID(){
+
+    window.location.pathname = pathname + '/' + app.helpers.GenerateInstanceID()
+
+  }
 
 
   HandleParsableRequestWithID(ctx) {
   HandleParsableRequestWithID(ctx) {
 
 
@@ -1375,9 +1397,28 @@ class App {
     console.log(ctx.params);
     console.log(ctx.params);
     var pathname = ctx.pathname;
     var pathname = ctx.pathname;
     let user = ctx.params.user;
     let user = ctx.params.user;
-    let genID = ctx.params.id;
     let space = ctx.params.space;
     let space = ctx.params.space;
     let savename = ctx.params.savename;
     let savename = ctx.params.savename;
+    //let genID = ctx.params.id;
+
+    let query = ctx.query;
+    var genID = undefined;
+
+    if(Object.keys(query).length > 0){
+      if(query.k){
+        genID = query.k
+      } 
+    }
+
+     if (!genID){
+       genID = app.helpers.GenerateInstanceID();
+       let urlAddon = '?k=' + genID;
+       let state = {
+         path: ctx.pathname + urlAddon
+       }
+       window.history.pushState(state, space, window.location.href + urlAddon);
+     }
+  
 
 
     if (pathname[pathname.length - 1] == '/') {
     if (pathname[pathname.length - 1] == '/') {
       pathname = pathname.slice(0, -1)
       pathname = pathname.slice(0, -1)
@@ -1796,8 +1837,12 @@ class App {
 
 
   hideProgressBar() {
   hideProgressBar() {
     let el = document.getElementById('loadscreen');
     let el = document.getElementById('loadscreen');
-    el.getElementsByClassName('spinner')[0].remove();
-    //window._spinner.stop(false);
+    if(el){
+      el.getElementsByClassName('spinner')[0].remove();
+      //window._spinner.stop(false);
+    }
+
+
   }
   }
 
 
   showProgressBar() {
   showProgressBar() {

+ 1 - 0
public/index.js

@@ -15,6 +15,7 @@ loadjs([
     '/lib/he.js',
     '/lib/he.js',
     '/lib/locale/polyglot.min.js',
     '/lib/locale/polyglot.min.js',
     '/lib/hashids.min.js',
     '/lib/hashids.min.js',
+    '/lib/page-query.js'
 ],'forall', {
 ],'forall', {
     async: false
     async: false
 });
 });

+ 260 - 0
public/lib/page-query.js

@@ -0,0 +1,260 @@
+(function(exports){
+
+/**
+ * Library version.
+ */
+
+exports.version = '0.4.2';
+
+/**
+ * Object#toString() ref for stringify().
+ */
+
+var toString = Object.prototype.toString;
+
+/**
+ * Cache non-integer test regexp.
+ */
+
+var isint = /^[0-9]+$/;
+
+function promote(parent, key) {
+  if (parent[key].length == 0) return parent[key] = {};
+  var t = {};
+  for (var i in parent[key]) t[i] = parent[key][i];
+  parent[key] = t;
+  return t;
+}
+
+function parse(parts, parent, key, val) {
+  var part = parts.shift();
+  // end
+  if (!part) {
+    if (Array.isArray(parent[key])) {
+      parent[key].push(val);
+    } else if ('object' == typeof parent[key]) {
+      parent[key] = val;
+    } else if ('undefined' == typeof parent[key]) {
+      parent[key] = val;
+    } else {
+      parent[key] = [parent[key], val];
+    }
+    // array
+  } else {
+    var obj = parent[key] = parent[key] || [];
+    if (']' == part) {
+      if (Array.isArray(obj)) {
+        if ('' != val) obj.push(val);
+      } else if ('object' == typeof obj) {
+        obj[Object.keys(obj).length] = val;
+      } else {
+        obj = parent[key] = [parent[key], val];
+      }
+      // prop
+    } else if (~part.indexOf(']')) {
+      part = part.substr(0, part.length - 1);
+      if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key);
+      parse(parts, obj, part, val);
+      // key
+    } else {
+      if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key);
+      parse(parts, obj, part, val);
+    }
+  }
+}
+
+/**
+ * Merge parent key/val pair.
+ */
+
+function merge(parent, key, val){
+  if (~key.indexOf(']')) {
+    var parts = key.split('[')
+      , len = parts.length
+      , last = len - 1;
+    parse(parts, parent, 'base', val);
+    // optimize
+  } else {
+    if (!isint.test(key) && Array.isArray(parent.base)) {
+      var t = {};
+      for (var k in parent.base) t[k] = parent.base[k];
+      parent.base = t;
+    }
+    set(parent.base, key, val);
+  }
+
+  return parent;
+}
+
+/**
+ * Parse the given obj.
+ */
+
+function parseObject(obj){
+  var ret = { base: {} };
+  Object.keys(obj).forEach(function(name){
+    merge(ret, name, obj[name]);
+  });
+  return ret.base;
+}
+
+/**
+ * Parse the given str.
+ */
+
+function parseString(str){
+  return String(str)
+    .split('&')
+    .reduce(function(ret, pair){
+      try{
+        pair = decodeURIComponent(pair.replace(/\+/g, ' '));
+      } catch(e) {
+        // ignore
+      }
+
+      var eql = pair.indexOf('=')
+        , brace = lastBraceInKey(pair)
+        , key = pair.substr(0, brace || eql)
+        , val = pair.substr(brace || eql, pair.length)
+        , val = val.substr(val.indexOf('=') + 1, val.length);
+
+      // ?foo
+      if ('' == key) key = pair, val = '';
+
+      return merge(ret, key, val);
+    }, { base: {} }).base;
+}
+
+/**
+ * Parse the given query `str` or `obj`, returning an object.
+ *
+ * @param {String} str | {Object} obj
+ * @return {Object}
+ * @api public
+ */
+
+exports.parse = function(str){
+  if (null == str || '' == str) return {};
+  return 'object' == typeof str
+    ? parseObject(str)
+    : parseString(str);
+};
+
+/**
+ * Turn the given `obj` into a query string
+ *
+ * @param {Object} obj
+ * @return {String}
+ * @api public
+ */
+
+var stringify = exports.stringify = function(obj, prefix) {
+  if (Array.isArray(obj)) {
+    return stringifyArray(obj, prefix);
+  } else if ('[object Object]' == toString.call(obj)) {
+    return stringifyObject(obj, prefix);
+  } else if ('string' == typeof obj) {
+    return stringifyString(obj, prefix);
+  } else {
+    return prefix + '=' + obj;
+  }
+};
+
+/**
+ * Stringify the given `str`.
+ *
+ * @param {String} str
+ * @param {String} prefix
+ * @return {String}
+ * @api private
+ */
+
+function stringifyString(str, prefix) {
+  if (!prefix) throw new TypeError('stringify expects an object');
+  return prefix + '=' + encodeURIComponent(str);
+}
+
+/**
+ * Stringify the given `arr`.
+ *
+ * @param {Array} arr
+ * @param {String} prefix
+ * @return {String}
+ * @api private
+ */
+
+function stringifyArray(arr, prefix) {
+  var ret = [];
+  if (!prefix) throw new TypeError('stringify expects an object');
+  for (var i = 0; i < arr.length; i++) {
+    ret.push(stringify(arr[i], prefix + '['+i+']'));
+  }
+  return ret.join('&');
+}
+
+/**
+ * Stringify the given `obj`.
+ *
+ * @param {Object} obj
+ * @param {String} prefix
+ * @return {String}
+ * @api private
+ */
+
+function stringifyObject(obj, prefix) {
+  var ret = []
+    , keys = Object.keys(obj)
+    , key;
+
+  for (var i = 0, len = keys.length; i < len; ++i) {
+    key = keys[i];
+    ret.push(stringify(obj[key], prefix
+      ? prefix + '[' + encodeURIComponent(key) + ']'
+      : encodeURIComponent(key)));
+  }
+
+  return ret.join('&');
+}
+
+/**
+ * Set `obj`'s `key` to `val` respecting
+ * the weird and wonderful syntax of a qs,
+ * where "foo=bar&foo=baz" becomes an array.
+ *
+ * @param {Object} obj
+ * @param {String} key
+ * @param {String} val
+ * @api private
+ */
+
+function set(obj, key, val) {
+  var v = obj[key];
+  if (undefined === v) {
+    obj[key] = val;
+  } else if (Array.isArray(v)) {
+    v.push(val);
+  } else {
+    obj[key] = [v, val];
+  }
+}
+
+/**
+ * Locate last brace in `str` within the key.
+ *
+ * @param {String} str
+ * @return {Number}
+ * @api private
+ */
+
+function lastBraceInKey(str) {
+  var len = str.length
+    , brace
+    , c;
+  for (var i = 0; i < len; ++i) {
+    c = str[i];
+    if (']' == c) brace = false;
+    if ('[' == c) brace = true;
+    if ('=' == c && !brace) return i;
+  }
+}
+})('undefined' == typeof exports ? qs = {} : exports);

+ 30 - 6
public/lib/page.mjs

@@ -879,7 +879,6 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
    * @param {string} href
    * @param {string} href
    * @api public
    * @api public
    */
    */
-
   Page.prototype.sameOrigin = function(href) {
   Page.prototype.sameOrigin = function(href) {
     if(!href || !isLocation) return false;
     if(!href || !isLocation) return false;
 
 
@@ -887,9 +886,18 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
     var window = this._window;
     var window = this._window;
 
 
     var loc = window.location;
     var loc = window.location;
+
+    /*
+       When the port is the default http port 80 for http, or 443 for
+       https, internet explorer 11 returns an empty string for loc.port,
+       so we need to compare loc.port with an empty string if url.port
+       is the default port 80 or 443.
+       Also the comparition with `port` is changed from `===` to `==` because
+       `port` can be a string sometimes. This only applies to ie11.
+    */
     return loc.protocol === url.protocol &&
     return loc.protocol === url.protocol &&
       loc.hostname === url.hostname &&
       loc.hostname === url.hostname &&
-      loc.port === url.port;
+      (loc.port === url.port || loc.port === '' && (url.port == 80 || url.port == 443)); // jshint ignore:line
   };
   };
 
 
   /**
   /**
@@ -1035,6 +1043,16 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
     isLocation && (window.location.href = ctx.canonicalPath);
     isLocation && (window.location.href = ctx.canonicalPath);
   }
   }
 
 
+  /**
+   * Escapes RegExp characters in the given string.
+   *
+   * @param {string} s
+   * @api private
+   */
+  function escapeRegExp(s) {
+    return s.replace(/([.+*?=^!:${}()[\]|/\\])/g, '\\$1');
+  }
+
   /**
   /**
    * Initialize a new "request" `Context`
    * Initialize a new "request" `Context`
    * with the given `path` and optional initial `state`.
    * with the given `path` and optional initial `state`.
@@ -1055,7 +1073,8 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
     var i = path.indexOf('?');
     var i = path.indexOf('?');
 
 
     this.canonicalPath = path;
     this.canonicalPath = path;
-    this.path = path.replace(pageBase, '') || '/';
+    var re = new RegExp('^' + escapeRegExp(pageBase));
+    this.path = path.replace(re, '') || '/';
     if (hashbang) this.path = this.path.replace('#!', '') || '/';
     if (hashbang) this.path = this.path.replace('#!', '') || '/';
 
 
     this.title = (hasDocument && window.document.title);
     this.title = (hasDocument && window.document.title);
@@ -1102,7 +1121,7 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
 
 
   Context.prototype.save = function() {
   Context.prototype.save = function() {
     var page = this.page;
     var page = this.page;
-    if (hasHistory && page._window.location.protocol !== 'file:') {
+    if (hasHistory) {
         page._window.history.replaceState(this.state, this.title,
         page._window.history.replaceState(this.state, this.title,
           page._hashbang && this.path !== '/' ? '#!' + this.path : this.canonicalPath);
           page._hashbang && this.path !== '/' ? '#!' + this.path : this.canonicalPath);
     }
     }
@@ -1126,7 +1145,7 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
   function Route(path, options, page) {
   function Route(path, options, page) {
     var _page = this.page = page || globalPage;
     var _page = this.page = page || globalPage;
     var opts = options || {};
     var opts = options || {};
-    opts.strict = opts.strict || page._strict;
+    opts.strict = opts.strict || _page._strict;
     this.path = (path === '*') ? '(.*)' : path;
     this.path = (path === '*') ? '(.*)' : path;
     this.method = 'GET';
     this.method = 'GET';
     this.regexp = pathToRegexp_1(this.path, this.keys = [], opts);
     this.regexp = pathToRegexp_1(this.path, this.keys = [], opts);
@@ -1144,7 +1163,10 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
   Route.prototype.middleware = function(fn) {
   Route.prototype.middleware = function(fn) {
     var self = this;
     var self = this;
     return function(ctx, next) {
     return function(ctx, next) {
-      if (self.match(ctx.path, ctx.params)) return fn(ctx, next);
+      if (self.match(ctx.path, ctx.params)) {
+        ctx.routePath = self.path;
+        return fn(ctx, next);
+      }
       next();
       next();
     };
     };
   };
   };
@@ -1167,6 +1189,8 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
 
 
     if (!m) return false;
     if (!m) return false;
 
 
+    delete params[0];
+
     for (var i = 1, len = m.length; i < len; ++i) {
     for (var i = 1, len = m.length; i < len; ++i) {
       var key = keys[i - 1];
       var key = keys[i - 1];
       var val = this.page._decodeURLEncodedURIComponent(m[i]);
       var val = this.page._decodeURLEncodedURIComponent(m[i]);

+ 2 - 2
public/web/index-app.js

@@ -455,7 +455,7 @@ class IndexApp {
                 if (m[1].loadInfo.save_name) {
                 if (m[1].loadInfo.save_name) {
                     link = "/" + m[1].user + "/" + worldName + "/" + instanceID + '/load/' + m[1].loadInfo.save_name;
                     link = "/" + m[1].user + "/" + worldName + "/" + instanceID + '/load/' + m[1].loadInfo.save_name;
                 } else {
                 } else {
-                    link = "/" + m[1].user + "/" + worldName + "/" + instanceID; //m[0];
+                    link = "/" + m[1].user + "/" + worldName + "?k=" + instanceID; //m[0];
                 }
                 }
 
 
                 return {
                 return {
@@ -479,7 +479,7 @@ class IndexApp {
                                             // href: window.location.protocol + "//" + window.location.host + "/" + m[1].user + m[0],
                                             // href: window.location.protocol + "//" + window.location.host + "/" + m[1].user + m[0],
                                             onclick: function (e) {
                                             onclick: function (e) {
                                                 self.checkForManualSettings();
                                                 self.checkForManualSettings();
-                                                window.location.pathname = link
+                                                window.location.href = window.location.origin + link
 
 
                                                 //self.refresh();
                                                 //self.refresh();
                                             }
                                             }