Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compatibility for better simulator reloads #35

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
def3895
added individualCompile option
yofreke Jul 19, 2015
282953d
updates for preloading
yofreke Jul 20, 2015
120f7cb
move jsio path cache to its own file
yofreke Jul 20, 2015
9fb2e4f
checkpoint - ~0.6 second simulator builds
yofreke Jul 21, 2015
132bc03
remove old comments
yofreke Jul 23, 2015
a4e2677
partial load (for preloading only and then waiting)
yofreke Jul 23, 2015
48b50ee
use FileGenerator for index.html and native-ios.js
yofreke Jul 23, 2015
f500a0a
support for new simulator (fake) spritesheet maps
yofreke Jul 24, 2015
8059d06
clean up + ensure broswer and native builds work
yofreke Jul 28, 2015
64fc51b
moved jsio dependency back to package.json
yofreke Jul 28, 2015
8ddc085
update spritesheetmapgenerator comments
yofreke Jul 28, 2015
86a4226
Merge branch 'master' into feature-individualCompile
yofreke Jul 28, 2015
3ec9fd5
doThings -> loadTargetJS
yofreke Jul 31, 2015
e655fa4
lower case FileGenerator
yofreke Jul 31, 2015
2b88f49
normal convention
yofreke Jul 31, 2015
9132381
normal import Promise
yofreke Jul 31, 2015
b859881
osx being bad at capitals
yofreke Jul 31, 2015
7b4cdbc
remove promise
yofreke Aug 4, 2015
473350d
mkdirp -> fs-extra.mkdirp
yofreke Aug 5, 2015
0bbfc52
no more server side compilation
yofreke Aug 5, 2015
8620a31
remove separateJsio option and replace it with simulator only functio…
yofreke Aug 5, 2015
c83a22d
use only top level dirs in pathCache instead of each individual file
yofreke Aug 5, 2015
9e8b8fd
use relative (no sym link resolution) jsio path
yofreke Aug 20, 2015
91f11c0
native: add a debugpath for native jsio env
Sep 16, 2015
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,3 @@
[submodule "modules/squill"]
path = modules/squill
url = https://github.com/gameclosure/squill
[submodule "node_modules/jsio"]
path = node_modules/jsio
url = https://github.com/gameclosure/js.io
1 change: 0 additions & 1 deletion node_modules/jsio
Submodule jsio deleted from a4a90e
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
"fs-extra": "^0.18.4",
"glob": "^5.0.2",
"graceful-fs": "^3.0.2",
"image-size": "0.3.2",
"jsio": "^2.2.0",
"image-size": "^0.3.2",
"jsio": "git+https://github.com/gameclosure/js.io#feat-noCompile",
"mime": "1.2.11",
"mkdirp": "0.5.0",
"nib": "1.0.3",
Expand Down
133 changes: 34 additions & 99 deletions src/build/browser/browser-static/bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,6 @@ function bootstrap(initialImport, target) {
var loc = w.location;
var q = loc.search + loc.hash;

// check to see if we need chrome frame
// if (target && (target=="desktop" || target=="facebook") && /MSIE/i.test(navigator.userAgent) && !d.createElement('canvas').getContext) {
// var chromeframe_url = 'chromeframe.html' + (loc.search ? loc.search + "&" : "?") + "target="+ target;
// bootstrap = function() {};
// try {
// var obj = new ActiveXObject('ChromeTab.ChromeFrame');
// if (!obj) {
// throw "bad object";
// }
// loc.replace(chromeframe_url);
// } catch(e) {
// w.onload = function() {
// var e = d.createElement('script');
// e.async = true;
// e.src = "http://ajax.googleapis.com/ajax/libs/chrome-frame/1/CFInstall.min.js";
// e.onreadystatechange= function () {
// if (this.readyState == 'loaded') {
// CFInstall.check({
// mode: "overlay",
// oninstall: function() { loc.replace(chromeframe_url) },
// url: "http://www.google.com/chromeframe/eula.html?user=true"
// });
// }
// }
// d.getElementsByTagName('head')[0].appendChild(e);
// }
// }
// return;
// }

// for tracking when the page started loading
w.__initialTime = +new Date();

Expand Down Expand Up @@ -75,18 +45,6 @@ function bootstrap(initialImport, target) {
var mobile = (/(iPod|iPhone|iPad)/i.test(ua) ? 'ios' : /BlackBerry/.test(ua) ? 'blackberry' : /Mobile Safari/.test(ua) ? 'android' : '');
var isKik = /Kik\/\d/.test(ua);

// if (loc.search.match(/exportSettings=true/)) {
// // just export localStorage
// exportSettings();
// } else if (mobile != 'blackberry' && !w.CONFIG.noRedirect) {
// // redirect based on device
// if (mobile && target != 'browser-mobile') {
// return loc.replace('//' + loc.host + '/browser-mobile/' + loc.hash);
// } else if (!mobile && target == 'browser-mobile') {
// return loc.replace('//' + loc.host + '/browser-desktop/' + loc.hash);
// }
// }

// set the viewport
if (mobile == 'ios') {
// Using initial-scale on android makes everything blurry! I think only IOS
Expand Down Expand Up @@ -134,11 +92,39 @@ function bootstrap(initialImport, target) {

var loaded = false;
w._continueLoad = function() {
if (!loaded) {
loaded = true;
var el = d.createElement('script');
el.src = target + '.js';
d.getElementsByTagName('head')[0].appendChild(el);
var doThings = function() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we not call this doThings? :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ugh

if (!loaded) {
loaded = true;
// Include the game code
var el = d.createElement('script');
el.src = target + '.js';
d.getElementsByTagName('head')[0].appendChild(el);
}
};

var _continueLoadDefer;

w.addEventListener('message', function(event) {
if (event.data === 'partialLoadContinue') {
if (_continueLoadDefer) {
_continueLoadDefer.resolve();
_continueLoadDefer = undefined;
}
}
});
// Preload suggestions and then tell the parent bootstrapping is complete
jsio.__env.preloadModules(function() {
w.parent.postMessage('bootstrapping', '*');
});

var partialLoadKey = jsio.__env.getNamespace('partialLoad');
if (localStorage && localStorage.getItem(partialLoadKey)) {
localStorage.removeItem(partialLoadKey);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is jsio namespacing only used for localStorage? If so, we should just solve the localStorage problem separately -- we can wrap the localStorage API in devkit on a per-app basis

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would mean that jsio functionality is reliant on devkit? Did it this way so that these changes would work with any jsio app

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I can tell, your proposed changes make jsio reliant on devkit functionality since it makes jsio.js getNamespace look for the global CONFIG and/or look for apps/ in the URL, both of which are state provided by devkit only. I'm proposing the alternative -- js.io doesn't depend on devkit, and any local storage namespacing or caching lives entirely in devkit -- no getNamespace calls from devkit to js.io that depend on devkit variables/state.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made the namespace calls not dependent on devkit. I think we probably should still leave them in there just to make sure they don't collide with some other project.


_continueLoadDefer = Promise.defer();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't think we have Promise yet in all browsers?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

by pretty decent you mean absolutely awful?

check the android browser column: less than 20% of that column has promises, and that's only android 4.1+ (not including users on 4.0 and lower).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually, i was wrong, it's still pretty bad though -- adding in chrome for android you get:

chrome android: 13.77%
android browser with promises: 1.13%
total android: 13.77 + 1.13 + 2.61 + 1.48 + 0.75
(13.77+1.13) / (13.77 + 1.13 + 2.61 + 1.48 + 0.75) == ~75%

so according to that particular website, about a 1 in 4 chance it fails on an arbitrary android device? i'd maybe buy the argument that devkit games only run on chrome for android and that we don't support the old android webkit, but chrome doesn't ship with android (oem's can choose to ship it i think) and I'm not sure which devices we'd actually expect to have chrome these days. Until Chrome is default on android or we have usage numbers of 90-95%+ chrome on android, I don't think it's wise to drop support for older browsers, and I'd definitely prefer some kind of nice you-need-to-upgrade message, not just have it throw an exception on load with a white screen.

_continueLoadDefer.promise.then(doThings);
} else {
doThings();
}
};

Expand Down Expand Up @@ -173,72 +159,21 @@ function bootstrap(initialImport, target) {

if (mobile && supportedOrientations) {
checkOrientation();
// if (!orientationOk) {
// var el = d.body.appendChild(d.createElement('div'));
// el.innerHTML = 'please rotate your phone<br><span style="font-size:200%">\u21bb</span>';
// var width = d.body.offsetWidth;
// el.style.cssText = 'opacity:0;z-index:9000;color:#FFF;background:rgba(40,40,40,0.8);border-radius:25px;text-align:center;padding:' + width / 10 + 'px;font-size:' + width / 20 + 'px;position:absolute;left:50%;width:' + width * 5 / 8 + 'px;margin-left:-' + width * 5 / 16 + 'px;margin-top:80px;pointer-events:none';
// w.addEventListener('resize', function () {
// checkOrientation();
// el.style.display = orientationOk ? 'none': 'block';
// });
// }
}

var appCache = window.applicationCache;
['cached', 'checking', 'downloading', 'error', 'noupdate', 'obsolete', 'progress', 'updateready'].forEach(function (evt) {
appCache.addEventListener(evt, handleCacheEvent, false);
});

// status 0 == UNCACHED
// if (appCache.status) {

// appCache.update(); // Attempt to update the user's cache.
// }

function handleCacheEvent(evt) {
if (evt.type == 'updateready') {
// var el = d.body.appendChild(d.createElement('div'));
// el.style.cssText = 'opacity:0;position:absolute;z-index:9900000;top:-20px;margin:0px auto'
// + 'height:20px;width:200px;'
// + '-webkit-border-radius:0px 0px 5px 5px;'
// + '-webkit-transition:all 0.7s ease-in-out;'
// + '-webkit-transform:scale(' + w.devicePixelRatio + ');'
// + '-webkit-transform-origin:50% 0%;'
// + '-webkit-box-shadow:0px 2px 3px rgba(0, 0, 0, 0.4);'
// + 'background:rgba(0,0,0,0.7);color:#FFF;'
// + 'padding:10px 15px;'
// + 'font-size: 15px;';
// + 'text-align: center;';
// + 'cursor:pointer;';

// if (CONFIG.embeddedFonts && CONFIG.embeddedFonts.length) {
// el.style.fontFamily = CONFIG.embeddedFonts[0];
// }

// el.innerText = 'game updated! tap here';
// el.style.left = (d.body.offsetWidth - 200) / 2 + 'px';

// el.setAttribute('noCapture', true); // prevent DevKit from stopping clicks on this event
// el.addEventListener('click', reload, true);
// el.addEventListener('touchstart', reload, true);

// setTimeout(function () {
// el.style.top='0px';
// el.style.opacity='1';
// }, 0);

// setTimeout(function () {
// el.style.top='-20px';
// el.style.opacity='0';
// }, 30000);
console.log("update ready");

// reload immediately if splash is still visible
var splash = d.getElementById('_GCSplash');
if (splash && splash.parentNode) {
try { appCache.swapCache(); } catch (e) {}
//location.reload();
}
}
}
Expand Down Expand Up @@ -284,6 +219,6 @@ function bootstrap(initialImport, target) {
if (h > min) { increased = true; }
min = h;
// }
}, 50);
}, 20);
}
}
72 changes: 61 additions & 11 deletions src/build/browser/html.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
var path = require('path');
var fs = require('fs');
var stylus = require('stylus');
var nib = require('nib');
var printf = require('printf');

var JSCompiler = require('../common/jsCompiler').JSCompiler;
var getBase64Image = require('./datauri').getBase64Image;

var FileGenerator = require('../common/FileGenerator');

var TARGET_APPLE_TOUCH_ICON_SIZE = 152;

exports.IndexHTML = Class(function () {
Expand Down Expand Up @@ -76,14 +76,64 @@ exports.IndexHTML = Class(function () {
};
});

var renderStylus = function(cssString, shouldCompress) {
// Only import if used, otherwise it takes forever
var stylus = require('stylus');
var nib = require('nib');

// process the stylus into css
var stylusRenderer = stylus(cssString)
.set('compress', shouldCompress)
.use(nib());
return stylusRenderer.render();
};

exports.GameHTML = Class(function () {
this.init = function () {
this.init = function (config) {
this._css = [];
this._js = [];

this._config = config;
this._binPath = path.join(config.outputPath, 'bin', 'html');
};

/**
* @param {string} css Path to some stylus file
*/
// TODO: Actually should be "addStylus"
this.addCSS = function (name, css) {
var dest = path.join(this._binPath, 'css', name.replace(/\//g, '_'));
var shouldCompress = this._config.compress;

this._css.push(FileGenerator.dynamic(
css,
dest,
function(cb) {
cb(null, renderStylus(css, shouldCompress));
}
));
};

this.addCSS = function (css) { this._css.push(css); };
this.addJS = function (js) { this._js.push(js); };
this.addCSSFile = function(cssPath) {
var dest = path.join(this._binPath, 'css', cssPath.replace(/\//g, '_'));
var shouldCompress = this._config.compress;

this._css.push(FileGenerator(
cssPath,
dest,
function(cb) {
fs.readFile(cssPath, 'utf8', function(err, cssSrc) {
if (err) { reject(err); return; }

cb(null, renderStylus(cssSrc, shouldCompress));
});
}
));
};

this.addJS = function (js) {
this._js.push(js);
};

// return smallest icon size larger than targetSize or the largest icon if
// none are larger than targetSize
Expand Down Expand Up @@ -126,16 +176,16 @@ exports.GameHTML = Class(function () {
this.generate = function (api, app, config) {
var logger = api.logging.get('build-html');

var css = this._css.join('\n');
var theCss = Promise.reduce(this._css, function(total, src) {
return total += src + '\n';
}, '');

var js = this._js.join(';');
var stylusRenderer = stylus(css)
.set('compress', config.compress)
.use(nib());
var jsCompiler = new JSCompiler(api, app);
var renderCSS = Promise.promisify(stylusRenderer.render, stylusRenderer);
var compileJS = Promise.promisify(jsCompiler.compress, jsCompiler);

return Promise.all([
renderCSS(),
theCss,
config.compress
? compileJS('[bootstrap]', js, {showWarnings: false})
: js
Expand Down
Loading