feeles-ide
Version:
The hackable and serializable IDE to make learning material
981 lines (828 loc) • 29.9 kB
JavaScript
import _Object$assign from 'babel-runtime/core-js/object/assign';
import _getIterator from 'babel-runtime/core-js/get-iterator';
import _Map from 'babel-runtime/core-js/map';
import _Object$values from 'babel-runtime/core-js/object/values';
import _toConsumableArray from 'babel-runtime/helpers/toConsumableArray';
import _slicedToArray from 'babel-runtime/helpers/slicedToArray';
import _extends from 'babel-runtime/helpers/extends';
import _regeneratorRuntime from 'babel-runtime/regenerator';
import _asyncToGenerator from 'babel-runtime/helpers/asyncToGenerator';
import _JSON$stringify from 'babel-runtime/core-js/json/stringify';
import _Object$getPrototypeOf from 'babel-runtime/core-js/object/get-prototype-of';
import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
import _createClass from 'babel-runtime/helpers/createClass';
import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
import _inherits from 'babel-runtime/helpers/inherits';
import _Promise from 'babel-runtime/core-js/promise';
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import Popout from '../../jsx/ReactPopout';
import { SourceFile, makeFromFile } from '../../File/';
import composeEnv from '../../File/composeEnv';
import Screen from './Screen';
import setSrcDoc from './setSrcDoc';
import registerHTML from './registerHTML';
import uniqueId from '../../utils/uniqueId';
import { getPrimaryUser } from '../../database/';
import fetchPonyfill from 'fetch-ponyfill';
var fetch = window.fetch ||
// for IE11
fetchPonyfill({
// TODO: use babel-runtime to rewrite this into require("babel-runtime/core-js/promise")
Promise: _Promise
}).fetch;
var ConnectionTimeout = 1000;
var popoutTemplate = '<!DOCTYPE html>\n<html>\n <head>\n <meta charset="utf-8">\n <style media="screen">\n body {\n margin: 0;\n }\n #popout-content-container {\n width: 100vw;\n height: 100vh;\n display: flex;\n }\n </style>\n </head>\n <body>\n </body>\n</html>\n';
var popoutURL = URL.createObjectURL(new Blob([popoutTemplate], { type: 'text/html' }));
var SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
var webkitSpeechGrammarList = window.webkitSpeechGrammarList;
var getStyle = function getStyle(props, context) {
var transitions = context.muiTheme.transitions;
var fullScreen = function fullScreen(yes, no) {
return props.isFullScreen ? yes : no;
};
return {
root: {
position: fullScreen('fixed', 'relative'),
width: '100%',
height: '100%',
left: 0,
top: 0,
boxSizing: 'border-box',
opacity: 1,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
overflow: 'hidden',
zIndex: 300,
transition: transitions.easeOut()
},
swap: {
position: 'absolute',
right: 0,
zIndex: 2
}
};
};
var Monitor = function (_PureComponent) {
_inherits(Monitor, _PureComponent);
function Monitor() {
var _ref;
var _temp, _this, _ret;
_classCallCheck(this, Monitor);
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = Monitor.__proto__ || _Object$getPrototypeOf(Monitor)).call.apply(_ref, [this].concat(args))), _this), _initialiseProps.call(_this), _temp), _possibleConstructorReturn(_this, _ret);
}
_createClass(Monitor, [{
key: 'componentWillMount',
value: function componentWillMount() {
// feeles.github.io/sample/#/path/to/index.html
window.addEventListener('hashchange', this.handleHashChanged);
if (/^#\//.test(location.hash)) {
this.handleHashChanged();
} else {
// default href で起動
this.props.setLocation();
}
var globalEvent = this.props.globalEvent;
var on = globalEvent.on.bind(globalEvent);
on('postMessage', this.handlePostMessage);
on('message.fetch', this.handleFetch);
on('message.resolve', this.handleResolve);
on('message.fetchDataURL', this.handleFetchDataURL);
on('message.saveAs', this.handleSaveAs);
on('message.reload', this.handleReload);
on('message.replace', this.handleReplace);
on('message.error', this.handleError);
on('message.ipcRenderer.*', this.handleIpcRenderer);
on('message.api.SpeechRecognition', this.handleSpeechRecognition);
on('message.setTimeout', this.handleSetTimeout);
on('message.clearTimeout', this.handleClearTimeout);
on('message.setInterval', this.handleSetInterval);
on('message.clearInterval', this.handleClearInterval);
on('message.openWindow', this.handleOpenWindow);
}
}, {
key: 'componentDidUpdate',
value: function componentDidUpdate(prevProps) {
var _this2 = this;
if (prevProps.reboot && !this.props.reboot) {
if (this.props.isPopout || this.popoutClosed) {
// react-popoutがpopoutWindowにDOMをrenderした後でstartする必要がある
// renderを補足するのは難しい&updateの度に何度もrenderされる=>delayを入れる
setTimeout(function () {
return _this2.start();
}, 500);
this.popoutClosed = false;
} else {
this.start();
}
}
if (prevProps.isPopout && !this.props.isPopout) {
this.popoutClosed = true; // Use delay
}
}
}, {
key: 'componentDidMount',
value: function componentDidMount() {
var _this3 = this;
if (window.ipcRenderer) {
this._emit = window.ipcRenderer.emit; // あとで戻せるようオリジナルを保持
var self = this;
window.ipcRenderer.emit = function () {
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
// ipcRenderer.emit をオーバーライドし, 全ての postMessage で送る
if (self.state && self.state.port) {
self.state.port.postMessage({
query: 'ipcRenderer.emit',
value: JSON.parse(_JSON$stringify(args))
});
}
_this3._emit.apply(_this3, args);
};
}
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
window.removeEventListener('hashchange', this.handleHashChanged);
if (window.ipcRenderer) {
// オリジナルの参照を戻す. Monitor が複数 mount されることはない(はず)
window.ipcRenderer.emit = this._emit;
}
}
}, {
key: 'start',
value: function () {
var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
var _this4 = this;
var _prevent;
return _regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_prevent = this.prevent;
this.prevent = _prevent.then(function () {
return _this4.startProcess();
}).catch(function (error) {
if (error) {
_this4.setState({ error: error });
} else if (_this4.props.isPopout) {
_this4.start();
}
});
_context.next = 4;
return _prevent;
case 4:
this.setState({ error: null, port: null });
case 5:
case 'end':
return _context.stop();
}
}
}, _callee, this);
}));
function start() {
return _ref2.apply(this, arguments);
}
return start;
}()
}, {
key: 'startProcess',
value: function () {
var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
var _this5 = this;
var _props, getConfig, findFile, env, versionUUIDFile, element, htmlFile, html, tryLoading, _ref4, port1, port2;
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
_props = this.props, getConfig = _props.getConfig, findFile = _props.findFile;
// env
env = composeEnv(getConfig('env'));
versionUUIDFile = findFile('feeles/.uuid');
if (versionUUIDFile) {
env.VERSION_UUID = versionUUIDFile.text;
} else {
// Backward compatibility
element = document.querySelector('meta[name="version_uuid"]');
if (element) {
env.VERSION_UUID = element.getAttribute('content');
}
}
_context2.next = 6;
return getPrimaryUser();
case 6:
env.USER_UUID = _context2.sent.uuid;
htmlFile = this.props.findFile(this.props.href) || SourceFile.html();
_context2.next = 10;
return registerHTML(htmlFile.text, this.props.findFile, env);
case 10:
html = _context2.sent;
tryLoading = function tryLoading() {
return new _Promise(function (resolve, reject) {
// iframe.srcdoc, onload => resolve
setSrcDoc(_this5.iframe, html, resolve);
// Connection timeouted, then retry
setTimeout(reject, ConnectionTimeout);
}).catch(function () {
return tryLoading();
});
};
_context2.next = 14;
return tryLoading();
case 14:
_ref4 = new MessageChannel(), port1 = _ref4.port1, port2 = _ref4.port2;
port1.addEventListener('message', function (event) {
var reply = function reply(params) {
params = _extends({ id: event.data.id }, params || {});
port1.postMessage(params);
};
var type = event.type,
data = event.data;
var name = data.query ? 'message.' + data.query : 'message';
_this5.props.globalEvent.emit(name, { type: type, data: data, reply: reply });
});
port1.start();
this.setState({ port: port1 });
this.iframe.contentWindow.postMessage({
env: env
}, '*', [port2]);
case 19:
case 'end':
return _context2.stop();
}
}
}, _callee2, this);
}));
function startProcess() {
return _ref3.apply(this, arguments);
}
return startProcess;
}()
}, {
key: 'render',
value: function render() {
var _this6 = this;
var error = this.state.error;
var _props2 = this.props,
isPopout = _props2.isPopout,
reboot = _props2.reboot;
var popout = isPopout && !reboot ? React.createElement(
Popout,
{
url: popoutURL,
title: 'app',
options: this.popoutOptions,
window: {
open: this.handlePopoutOpen,
addEventListener: window.addEventListener.bind(window),
removeEventListener: window.removeEventListener.bind(window)
},
onClosing: this.handlePopoutClose
},
React.createElement(Screen, {
display: true,
frameRef: this.handleFrame,
handleReload: function handleReload() {
return _this6.props.setLocation();
},
reboot: reboot,
error: error,
width: this.props.frameWidth,
height: this.props.frameHeight
})
) : null;
var styles = getStyle(this.props, this.context, this.state);
return React.createElement(
'div',
{ style: styles.root, onClick: this.handleTouch },
popout,
React.createElement(Screen, {
animation: true,
display: !isPopout,
frameRef: this.handleFrame,
reboot: reboot,
error: error,
width: this.props.frameWidth,
height: this.props.frameHeight,
isFullScreen: this.props.isFullScreen
})
);
}
}, {
key: 'iframe',
get: function get() {
return this.props.isPopout ? this.popoutFrame : this.inlineFrame;
}
}]);
return Monitor;
}(PureComponent);
Monitor.propTypes = {
files: PropTypes.array.isRequired,
cards: PropTypes.object.isRequired,
isPopout: PropTypes.bool.isRequired,
isFullScreen: PropTypes.bool.isRequired,
reboot: PropTypes.bool.isRequired,
href: PropTypes.string.isRequired,
togglePopout: PropTypes.func.isRequired,
toggleFullScreen: PropTypes.func.isRequired,
localization: PropTypes.object.isRequired,
getConfig: PropTypes.func.isRequired,
addFile: PropTypes.func.isRequired,
findFile: PropTypes.func.isRequired,
putFile: PropTypes.func.isRequired,
setLocation: PropTypes.func.isRequired,
frameWidth: PropTypes.number.isRequired,
frameHeight: PropTypes.number.isRequired,
globalEvent: PropTypes.object.isRequired
};
Monitor.contextTypes = {
muiTheme: PropTypes.object.isRequired
};
var _initialiseProps = function _initialiseProps() {
var _this7 = this;
this.state = {
error: null,
port: null
};
this.popoutOptions = {
width: 300,
height: 150, // means innerHeight of browser expecting Safari.
left: 50,
top: 50
};
this.popoutClosed = false;
this.prevent = _Promise.resolve();
this.handlePostMessage = function (value) {
// emitAsync('postMessage', value)
var port = _this7.state.port;
if (!port) return;
// reply を receive するための id
value = _extends({ id: uniqueId() }, value);
return new _Promise(function (resolve) {
// catch reply message (once)
var task = function task(event) {
if (!event.data || event.data.id !== value.id) return;
if (port) port.removeEventListener('message', task);
resolve(event.data);
};
port.addEventListener('message', task);
// post message to frame
port.postMessage(value);
});
};
this.handleFetch = function () {
var _ref5 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(_ref6) {
var data = _ref6.data,
reply = _ref6.reply;
var file, response, blob;
return _regeneratorRuntime.wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
file = _this7.props.findFile(data.value);
if (!file) {
_context3.next = 5;
break;
}
reply({ value: file.blob });
_context3.next = 22;
break;
case 5:
if (!(data.value.indexOf('http') === 0)) {
_context3.next = 21;
break;
}
_context3.prev = 6;
_context3.next = 9;
return fetch(data.value);
case 9:
response = _context3.sent;
_context3.next = 12;
return response.blob();
case 12:
blob = _context3.sent;
reply({ value: blob });
_context3.next = 19;
break;
case 16:
_context3.prev = 16;
_context3.t0 = _context3['catch'](6);
reply({ error: _context3.t0 });
case 19:
_context3.next = 22;
break;
case 21:
reply({ error: true });
case 22:
case 'end':
return _context3.stop();
}
}
}, _callee3, _this7, [[6, 16]]);
}));
return function (_x) {
return _ref5.apply(this, arguments);
};
}();
this.handleResolve = function () {
var _ref7 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4(_ref8) {
var data = _ref8.data,
reply = _ref8.reply;
var file, babelrc, result, response, text;
return _regeneratorRuntime.wrap(function _callee4$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
file = _this7.props.findFile(data.value + '.js') || _this7.props.findFile(data.value);
if (!file) {
_context4.next = 9;
break;
}
babelrc = _this7.props.getConfig('babelrc');
_context4.next = 5;
return file.babel(babelrc, function (e) {
reply({ error: e });
});
case 5:
result = _context4.sent;
if (result) {
reply({ value: result.text });
}
_context4.next = 26;
break;
case 9:
if (!(data.value.indexOf('http') === 0)) {
_context4.next = 25;
break;
}
_context4.prev = 10;
_context4.next = 13;
return fetch(data.value);
case 13:
response = _context4.sent;
_context4.next = 16;
return response.text();
case 16:
text = _context4.sent;
reply({ value: text });
_context4.next = 23;
break;
case 20:
_context4.prev = 20;
_context4.t0 = _context4['catch'](10);
reply({ error: _context4.t0 });
case 23:
_context4.next = 26;
break;
case 25:
reply({ error: true });
case 26:
case 'end':
return _context4.stop();
}
}
}, _callee4, _this7, [[10, 20]]);
}));
return function (_x2) {
return _ref7.apply(this, arguments);
};
}();
this.handleFetchDataURL = function () {
var _ref9 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee5(_ref10) {
var data = _ref10.data,
reply = _ref10.reply;
var file, response, blob, fileReader;
return _regeneratorRuntime.wrap(function _callee5$(_context5) {
while (1) {
switch (_context5.prev = _context5.next) {
case 0:
file = _this7.props.findFile(data.value);
if (!file) {
_context5.next = 10;
break;
}
_context5.t0 = reply;
_context5.next = 5;
return file.toDataURL();
case 5:
_context5.t1 = _context5.sent;
_context5.t2 = {
value: _context5.t1
};
(0, _context5.t0)(_context5.t2);
_context5.next = 29;
break;
case 10:
if (!(data.value.indexOf('http') === 0)) {
_context5.next = 28;
break;
}
_context5.prev = 11;
_context5.next = 14;
return fetch(data.value);
case 14:
response = _context5.sent;
_context5.next = 17;
return response.blob();
case 17:
blob = _context5.sent;
fileReader = new FileReader();
fileReader.onload = function () {
reply({ value: fileReader.result });
};
fileReader.readAsDataURL(blob);
_context5.next = 26;
break;
case 23:
_context5.prev = 23;
_context5.t3 = _context5['catch'](11);
reply({ error: _context5.t3 });
case 26:
_context5.next = 29;
break;
case 28:
reply({ error: true });
case 29:
case 'end':
return _context5.stop();
}
}
}, _callee5, _this7, [[11, 23]]);
}));
return function (_x3) {
return _ref9.apply(this, arguments);
};
}();
this.handleSaveAs = function () {
var _ref11 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee6(_ref12) {
var data = _ref12.data,
reply = _ref12.reply;
var _data$value, blob, name, file3, exist, key;
return _regeneratorRuntime.wrap(function _callee6$(_context6) {
while (1) {
switch (_context6.prev = _context6.next) {
case 0:
_data$value = _slicedToArray(data.value, 2), blob = _data$value[0], name = _data$value[1];
_context6.next = 3;
return makeFromFile(blob);
case 3:
file3 = _context6.sent;
exist = _this7.props.findFile(name);
if (!exist) {
_context6.next = 11;
break;
}
key = exist.key;
_context6.next = 9;
return _this7.props.putFile(exist, file3.set({ key: key, name: name }));
case 9:
_context6.next = 13;
break;
case 11:
_context6.next = 13;
return _this7.props.addFile(file3.set({ name: name }));
case 13:
reply();
case 14:
case 'end':
return _context6.stop();
}
}
}, _callee6, _this7);
}));
return function (_x4) {
return _ref11.apply(this, arguments);
};
}();
this.handleReload = function () {
_this7.props.setLocation();
};
this.handleReplace = function (_ref13) {
var data = _ref13.data;
location.hash = data.value.replace(/^\/*/, '/');
};
this.handleError = function (_ref14) {
var data = _ref14.data;
if (!_this7.state.error) {
_this7.setState({
error: new Error(data.value)
});
}
};
this.handleIpcRenderer = function (_ref15) {
var data = _ref15.data;
if (window.ipcRenderer) {
var _window$ipcRenderer;
(_window$ipcRenderer = window.ipcRenderer).sendToHost.apply(_window$ipcRenderer, _toConsumableArray(_Object$values(data.value)));
} else {
console.warn('window.ipcRenderer is not defined');
}
};
this.setTimeoutId = new _Map();
this.handleSetTimeout = function (_ref16) {
var data = _ref16.data,
reply = _ref16.reply;
var _data$value2 = data.value,
timeoutId = _data$value2.timeoutId,
delay = _data$value2.delay;
_this7.setTimeoutId.set(timeoutId, setTimeout(reply, delay));
};
this.handleClearTimeout = function (_ref17) {
var data = _ref17.data;
clearInterval(_this7.setTimeoutId.get(data.value.timeoutId));
};
this.setIntervalId = new _Map();
this.handleSetInterval = function (_ref18) {
var data = _ref18.data,
reply = _ref18.reply;
var _data$value3 = data.value,
intervalId = _data$value3.intervalId,
delay = _data$value3.delay;
_this7.setIntervalId.set(intervalId, setInterval(reply, delay));
};
this.handleClearInterval = function (_ref19) {
var data = _ref19.data;
clearInterval(_this7.setIntervalId.get(data.value.intervalId));
};
this.handleOpenWindow = function (_ref20) {
var value = _ref20.data.value;
// value.url が相対パスかどうかを調べる
var a = document.createElement('a');
a.href = value.url;
if (a.host === location.host) {
window.open(value.url, value.target, value.features, value.replace);
} else {
throw new Error('Cannot open ' + value.url);
}
};
this.handleSpeechRecognition = function (_ref21) {
var data = _ref21.data,
reply = _ref21.reply;
var recognition = new SpeechRecognition();
var _arr = ['lang', 'continuous', 'interimResults', 'maxAlternatives', 'serviceURI'];
for (var _i = 0; _i < _arr.length; _i++) {
var prop = _arr[_i];
if (data.value[prop] !== undefined) {
recognition[prop] = data.value[prop];
}
}
if (Array.isArray(data.value.grammars)) {
recognition.grammars = new webkitSpeechGrammarList();
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = _getIterator(data.value.grammars), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var _ref23 = _step.value;
var src = _ref23.src,
weight = _ref23.weight;
recognition.grammars.addFromString(src, weight);
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
}
recognition.onresult = function (event) {
var results = [];
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = _getIterator(event.results), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var items = _step2.value;
var result = [];
result.isFinal = items.isFinal;
var _iteratorNormalCompletion3 = true;
var _didIteratorError3 = false;
var _iteratorError3 = undefined;
try {
for (var _iterator3 = _getIterator(items), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
var _ref25 = _step3.value;
var confidence = _ref25.confidence,
transcript = _ref25.transcript;
result.push({ confidence: confidence, transcript: transcript });
}
} catch (err) {
_didIteratorError3 = true;
_iteratorError3 = err;
} finally {
try {
if (!_iteratorNormalCompletion3 && _iterator3.return) {
_iterator3.return();
}
} finally {
if (_didIteratorError3) {
throw _iteratorError3;
}
}
}
results.push(result);
}
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2.return) {
_iterator2.return();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
reply({
type: 'result',
event: {
results: results
}
});
};
recognition.onerror = function (event) {
reply({
type: 'error',
event: {
error: event.error
}
});
};
['audioend', 'audiostart', 'end', 'nomatch', 'soundend', 'soundstart', 'speechend', 'speechstart', 'start'].forEach(function (type) {
recognition['on' + type] = function () {
reply({ type: type });
};
});
recognition.start();
};
this.handlePopoutOpen = function () {
for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
args[_key3] = arguments[_key3];
}
_this7.parent = window.open.apply(window, args);
if (_this7.parent) {
_this7.parent.addEventListener('load', function () {
var out = _this7.popoutOptions.height !== _this7.parent.innerHeight;
_this7.parent.addEventListener('resize', function () {
_this7.popoutOptions = _Object$assign({}, _this7.popoutOptions, {
width: _this7.parent.innerWidth,
height: out ? _this7.parent.outerHeight : _this7.parent.innerHeight
});
});
var popoutMove = setInterval(function () {
if (_this7.parent.screenX === _this7.popoutOptions.left && _this7.parent.screenY === _this7.popoutOptions.top) {
return;
}
_this7.popoutOptions = _Object$assign({}, _this7.popoutOptions, {
left: _this7.parent.screenX,
top: _this7.parent.screenY
});
}, 100);
_this7.parent.addEventListener('beforeunload', function () {
clearInterval(popoutMove);
});
});
}
return _this7.parent;
};
this.handlePopoutClose = function () {
if (_this7.props.isPopout && !_this7.props.reboot) {
_this7.props.togglePopout();
}
};
this.handleFrame = function (ref) {
if (!_this7.props.isPopout) {
_this7.inlineFrame = ref;
} else {
_this7.popoutFrame = ref;
}
};
this.handleTouch = function () {
if (_this7.props.isFullScreen) {
_this7.props.toggleFullScreen();
}
};
this.handleHashChanged = function () {
if (/^#\//.test(location.hash)) {
var href = location.hash.substr(2);
_this7.props.setLocation(href);
}
};
};
export default Monitor;