diff --git a/.modernizr.json b/.modernizr.json
new file mode 100644
index 0000000000..29e620a5ba
--- /dev/null
+++ b/.modernizr.json
@@ -0,0 +1,14 @@
+{
+ "minify": true,
+ "classPrefix": "modernizr_",
+ "options": [
+ "setClasses"
+ ],
+ "feature-detects": [
+ "test/css/displaytable",
+ "test/css/flexbox",
+ "test/es5/specification",
+ "test/css/objectfit",
+ "test/storage/localstorage"
+ ]
+}
\ No newline at end of file
diff --git a/package.json b/package.json
index cab45e836d..27302a745d 100644
--- a/package.json
+++ b/package.json
@@ -11,6 +11,7 @@
"style": "bundle.css",
"scripts": {
"reskindex": "reskindex vector -h src/skins/vector/header",
+ "build:modernizr": "modernizr -c .modernizr.json -d src/vector/modernizr.js",
"build:css": "catw \"src/skins/vector/css/**/*.css\" -o vector/bundle.css -c uglifycss --no-watch",
"build:compile": "babel --source-maps -d lib src",
"build:bundle": "NODE_ENV=production webpack -p lib/vector/index.js vector/bundle.js",
@@ -27,6 +28,7 @@
"filesize": "^3.1.2",
"flux": "~2.0.3",
"linkifyjs": "^2.0.0-beta.4",
+ "modernizr": "^3.1.0",
"matrix-js-sdk": "^0.3.0",
"matrix-react-sdk": "^0.0.2",
"q": "^1.4.1",
diff --git a/src/skins/vector/css/pages/CompatibilityPage.css b/src/skins/vector/css/pages/CompatibilityPage.css
new file mode 100644
index 0000000000..f3f032c975
--- /dev/null
+++ b/src/skins/vector/css/pages/CompatibilityPage.css
@@ -0,0 +1,19 @@
+.mx_CompatibilityPage {
+ width: 100%;
+ height: 100%;
+ background-color: #e55;
+}
+
+.mx_CompatibilityPage_box {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ margin: auto;
+ width: 500px;
+ height: 300px;
+ border: 1px solid;
+ padding: 10px;
+ background-color: #fcc;
+}
\ No newline at end of file
diff --git a/src/skins/vector/views/pages/CompatibilityPage.js b/src/skins/vector/views/pages/CompatibilityPage.js
new file mode 100644
index 0000000000..129ed512bf
--- /dev/null
+++ b/src/skins/vector/views/pages/CompatibilityPage.js
@@ -0,0 +1,62 @@
+/*
+Copyright 2015 OpenMarket Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+'use strict';
+
+var React = require('react');
+
+module.exports = React.createClass({
+ displayName: 'CompatibilityPage',
+ propTypes: {
+ onAccept: React.PropTypes.func
+ },
+
+ getDefaultProps: function() {
+ return {
+ onAccept: function() {} // NOP
+ };
+ },
+
+ onAccept: function() {
+ this.props.onAccept();
+ },
+
+ render: function() {
+
+ return (
+
+
+
Sorry, your browser is not able to run Vector.
+
+ Buttons and images may appear out of place, communication may
+ not be possible and all manner of chaos may be unleashed.
+
+
+ Please install Chrome for
+ the best experience.
+
+
+ Though if you like taking risks with your life, you can still try it
+ out by clicking that you understand the risks involved.
+
+
+
+
+ );
+ }
+});
diff --git a/src/vector/index.js b/src/vector/index.js
index 22db05a38f..298861973e 100644
--- a/src/vector/index.js
+++ b/src/vector/index.js
@@ -16,6 +16,7 @@ limitations under the License.
'use strict';
+var RunModernizrTests = require("./modernizr"); // this side-effects a global
var React = require("react");
var sdk = require("matrix-react-sdk");
sdk.loadSkin(require('../skins/vector/skindex'));
@@ -25,6 +26,34 @@ var qs = require("querystring");
var lastLocationHashSet = null;
+function checkBrowserFeatures(featureList) {
+ if (!window.Modernizr) {
+ console.error("Cannot check features - Modernizr global is missing.");
+ return false;
+ }
+ var featureComplete = true;
+ for (var i = 0; i < featureList.length; i++) {
+ if (window.Modernizr[featureList[i]] === undefined) {
+ console.error(
+ "Looked for feature '%s' but Modernizr has no results for this. " +
+ "Has it been configured correctly?", featureList[i]
+ );
+ return false;
+ }
+ if (window.Modernizr[featureList[i]] === false) {
+ console.error("Browser missing feature: '%s'", featureList[i]);
+ // toggle flag rather than return early so we log all missing features
+ // rather than just the first.
+ featureComplete = false;
+ }
+ }
+ return featureComplete;
+}
+
+var validBrowser = checkBrowserFeatures([
+ "displaytable", "flexbox", "es5object", "es5function", "localstorage",
+ "objectfit"
+]);
// We want to support some name / value pairs in the fragment
// so we're re-using query string like format
@@ -84,14 +113,11 @@ var makeRegistrationUrl = function() {
'#/register';
}
-var MatrixChat = sdk.getComponent('pages.MatrixChat');
-window.matrixChat = React.render(
- ,
- document.getElementById('matrixchat')
-);
-
window.addEventListener('hashchange', onHashChange);
window.onload = function() {
+ if (!validBrowser) {
+ return;
+ }
routeUrl(window.location);
loaded = true;
if (lastLoadedScreen) {
@@ -100,3 +126,28 @@ window.onload = function() {
}
}
+function loadApp() {
+ if (validBrowser) {
+ var MatrixChat = sdk.getComponent('pages.MatrixChat');
+ window.matrixChat = React.render(
+ ,
+ document.getElementById('matrixchat')
+ );
+ }
+ else {
+ console.error("Browser is missing required features.");
+ // take to a different landing page to AWOOOOOGA at the user
+ var CompatibilityPage = require("../skins/vector/views/pages/CompatibilityPage");
+ window.matrixChat = React.render(
+ ,
+ document.getElementById('matrixchat')
+ );
+ }
+}
+
+loadApp();
diff --git a/src/vector/modernizr.js b/src/vector/modernizr.js
new file mode 100644
index 0000000000..5ef7778aeb
--- /dev/null
+++ b/src/vector/modernizr.js
@@ -0,0 +1,3 @@
+/*! modernizr 3.1.0 (Custom Build) | MIT *
+ * http://modernizr.com/download/?-displaytable-es5-flexbox-localstorage-objectfit-cssclassprefix:modernizr_ !*/
+!function(window,document,undefined){function is(e,t){return typeof e===t}function testRunner(){var e,t,r,n,o,s,i;for(var d in tests){if(e=[],t=tests[d],t.name&&(e.push(t.name.toLowerCase()),t.options&&t.options.aliases&&t.options.aliases.length))for(r=0;rd;d++)if(l=e[d],c=mStyle.style[l],contains(l,"-")&&(l=cssToDOM(l)),mStyle.style[l]!==undefined){if(n||is(r,"undefined"))return o(),"pfx"==t?l:!0;try{mStyle.style[l]=r}catch(u){}if(mStyle.style[l]!=c)return o(),"pfx"==t?l:!0}return o(),!1}function fnBind(e,t){return function(){return e.apply(t,arguments)}}function testDOMProps(e,t,r){var n;for(var o in e)if(e[o]in t)return r===!1?e[o]:(n=t[e[o]],is(n,"function")?fnBind(n,r||t):n);return!1}function testPropsAll(e,t,r,n,o){var s=e.charAt(0).toUpperCase()+e.slice(1),i=(e+" "+cssomPrefixes.join(s+" ")+s).split(" ");return is(t,"string")||is(t,"undefined")?testProps(i,t,n,o):(i=(e+" "+domPrefixes.join(s+" ")+s).split(" "),testDOMProps(i,t,r))}function testAllProps(e,t,r){return testPropsAll(e,undefined,undefined,t,r)}var tests=[],ModernizrProto={_version:"3.1.0",_config:{classPrefix:"modernizr_",enableClasses:!0,enableJSClass:!0,usePrefixes:!0},_q:[],on:function(e,t){var r=this;setTimeout(function(){t(r[e])},0)},addTest:function(e,t,r){tests.push({name:e,fn:t,options:r})},addAsyncTest:function(e){tests.push({name:null,fn:e})}},Modernizr=function(){};Modernizr.prototype=ModernizrProto,Modernizr=new Modernizr;var classes=[],docElement=document.documentElement,isSVG="svg"===docElement.nodeName.toLowerCase(),testStyles=ModernizrProto.testStyles=injectElementWithStyles;testStyles("#modernizr{display: table; direction: ltr}#modernizr div{display: table-cell; padding: 10px}",function(e){var t,r=e.childNodes;t=r[0].offsetLefto;o++){var s=prefixes[o],i=s.toUpperCase()+"_"+t;if(i in n)return"@-"+s.toLowerCase()+"-"+e}return!1};ModernizrProto.atRule=atRule;var prefixed=ModernizrProto.prefixed=function(e,t,r){return 0===e.indexOf("@")?atRule(e):(-1!=e.indexOf("-")&&(e=cssToDOM(e)),t?testPropsAll(e,t,r):testPropsAll(e,"pfx"))};Modernizr.addTest("objectfit",!!prefixed("objectFit"),{aliases:["object-fit"]}),Modernizr.addTest("localstorage",function(){var e="modernizr";try{return localStorage.setItem(e,e),localStorage.removeItem(e),!0}catch(t){return!1}}),testRunner(),setClasses(classes),delete ModernizrProto.addTest,delete ModernizrProto.addAsyncTest;for(var i=0;i