UNPKG

feeles-ide

Version:

The hackable and serializable IDE to make learning material

602 lines (518 loc) 19.5 kB
import _slicedToArray from 'babel-runtime/helpers/slicedToArray'; import _Object$entries from 'babel-runtime/core-js/object/entries'; import _getIterator from 'babel-runtime/core-js/get-iterator'; import _JSON$stringify from 'babel-runtime/core-js/json/stringify'; import _Object$keys from 'babel-runtime/core-js/object/keys'; import _regeneratorRuntime from 'babel-runtime/regenerator'; import _defineProperty from 'babel-runtime/helpers/defineProperty'; import _extends from 'babel-runtime/helpers/extends'; import _asyncToGenerator from 'babel-runtime/helpers/asyncToGenerator'; 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 md5 from 'md5'; import URLSearchParams from 'url-search-params'; import Card from '../CardWindow'; import { CardActions } from 'material-ui/Card'; import { GridList, GridTile } from 'material-ui/GridList'; import FlatButton from 'material-ui/FlatButton'; import ImagePhotoCamera from 'material-ui/svg-icons/image/photo-camera'; import ActionDelete from 'material-ui/svg-icons/action/delete'; import { emphasize, fade } from 'material-ui/utils/colorManipulator'; import organization from '../../organization'; import debugWindow from '../../utils/debugWindow'; import { SourceFile } from '../../File/'; 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 ScreenShotCard = function (_PureComponent) { _inherits(ScreenShotCard, _PureComponent); function ScreenShotCard() { var _ref, _this2 = this; var _temp, _this, _ret; _classCallCheck(this, ScreenShotCard); for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = ScreenShotCard.__proto__ || _Object$getPrototypeOf(ScreenShotCard)).call.apply(_ref, [this].concat(args))), _this), _this.state = { cache: {}, selected: null, uploading: null }, _this.handleSelect = function (event) { var selected = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; event.stopPropagation(); if (_this.state.selected === selected) { selected = null; // toggle } _this.setState({ selected: selected }); }, _this.handleCapture = function () { var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(event) { var value, uploading, cache, url; return _regeneratorRuntime.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: value = event.data.value; uploading = md5(value); // キャッシュを確認 if (!(uploading in _this.state.cache)) { _context2.next = 8; break; } _context2.next = 5; return _this.props.updateCard('ScreenShotCard', { visible: true }); case 5: _this.props.cardPropsBag.scrollToCard('ScreenShotCard'); _this.setState({ selected: uploading }); return _context2.abrupt('return'); case 8: // アップロードの前に仮の URL を挿入 cache = _extends({}, _this.state.cache, _defineProperty({}, uploading, [value])); _this.setState({ cache: cache, uploading: uploading }, _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() { return _regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: _context.next = 2; return _this.props.updateCard('ScreenShotCard', { visible: true }); case 2: _this.props.cardPropsBag.scrollToCard('ScreenShotCard'); case 3: case 'end': return _context.stop(); } } }, _callee, _this2); }))); // サムネイルをアップロード _context2.next = 12; return _this.uploadThumbnail(value); case 12: url = _context2.sent; _context2.next = 15; return _this.setCache(uploading, url); case 15: _this.setState({ uploading: null }); // サムネイルをセット _this.setState({ selected: uploading }, _this.handleThumbnailSet); case 17: case 'end': return _context2.stop(); } } }, _callee2, _this2); })); return function (_x2) { return _ref2.apply(this, arguments); }; }(), _this.handleThumbnailSet = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3() { var _this$state, selected, uploading, cache, url, ogp; return _regeneratorRuntime.wrap(function _callee3$(_context3) { while (1) { switch (_context3.prev = _context3.next) { case 0: _this$state = _this.state, selected = _this$state.selected, uploading = _this$state.uploading, cache = _this$state.cache; if (!(selected === uploading)) { _context3.next = 3; break; } return _context3.abrupt('return'); case 3: url = cache[selected]; ogp = _extends({}, _this.props.getConfig('ogp'), { 'og:image': url, 'twitter:image': url }); _context3.next = 7; return _this.props.setConfig('ogp', ogp); case 7: _this.props.showNotice({ message: _this.props.localization.screenShotCard.set }); case 8: case 'end': return _context3.stop(); } } }, _callee3, _this2); })), _this.handleThumbnailDelete = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4() { var selected, keys, index, next; return _regeneratorRuntime.wrap(function _callee4$(_context4) { while (1) { switch (_context4.prev = _context4.next) { case 0: selected = _this.state.selected; // 選択アイテムを削除 _context4.next = 3; return _this.setCache(selected, undefined); case 3: // 選択アイテムをとなりに移動 keys = _Object$keys(_this.state.cache); index = keys.indexOf(selected); next = keys[index + 1] || keys[index - 1] || null; _this.setState({ selected: next }); case 7: case 'end': return _context4.stop(); } } }, _callee4, _this2); })), _temp), _possibleConstructorReturn(_this, _ret); } _createClass(ScreenShotCard, [{ key: 'componentWillMount', value: function () { var _ref6 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee5() { var globalEvent; return _regeneratorRuntime.wrap(function _callee5$(_context5) { while (1) { switch (_context5.prev = _context5.next) { case 0: globalEvent = this.props.globalEvent; globalEvent.on('message.capture', this.handleCapture); _context5.t0 = this; _context5.next = 5; return this.getCache(); case 5: _context5.t1 = _context5.sent; _context5.t2 = { cache: _context5.t1 }; _context5.t0.setState.call(_context5.t0, _context5.t2); case 8: case 'end': return _context5.stop(); } } }, _callee5, this); })); function componentWillMount() { return _ref6.apply(this, arguments); } return componentWillMount; }() }, { key: 'componentWillReceiveProps', value: function () { var _ref7 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee6(nextProps) { return _regeneratorRuntime.wrap(function _callee6$(_context6) { while (1) { switch (_context6.prev = _context6.next) { case 0: if (!(this.props.files !== nextProps.files)) { _context6.next = 7; break; } _context6.t0 = this; _context6.next = 4; return this.getCache(); case 4: _context6.t1 = _context6.sent; _context6.t2 = { cache: _context6.t1 }; _context6.t0.setState.call(_context6.t0, _context6.t2); case 7: case 'end': return _context6.stop(); } } }, _callee6, this); })); function componentWillReceiveProps(_x3) { return _ref7.apply(this, arguments); } return componentWillReceiveProps; }() }, { key: 'getCache', value: function () { var _ref8 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee7() { var file; return _regeneratorRuntime.wrap(function _callee7$(_context7) { while (1) { switch (_context7.prev = _context7.next) { case 0: file = this.props.findFile(ScreenShotCard.fileName); _context7.prev = 1; return _context7.abrupt('return', JSON.parse(file.text)); case 5: _context7.prev = 5; _context7.t0 = _context7['catch'](1); return _context7.abrupt('return', this.state.cache); case 8: case 'end': return _context7.stop(); } } }, _callee7, this, [[1, 5]]); })); function getCache() { return _ref8.apply(this, arguments); } return getCache; }() }, { key: 'setCache', value: function () { var _ref9 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee8(hash, url) { var prevFile, next, text, nextFile, _nextFile; return _regeneratorRuntime.wrap(function _callee8$(_context8) { while (1) { switch (_context8.prev = _context8.next) { case 0: prevFile = this.props.findFile(ScreenShotCard.fileName); next = void 0; try { next = JSON.parse(prevFile.text); } catch (e) { next = _extends({}, this.state.cache); } // update data next[hash] = url; text = _JSON$stringify(next); // update file if (!prevFile) { _context8.next = 11; break; } // file is exist. replace it nextFile = prevFile.set({ text: text }); _context8.next = 9; return this.props.putFile(prevFile, nextFile); case 9: _context8.next = 14; break; case 11: // file is missing. insert it _nextFile = new SourceFile({ type: 'application/json', name: ScreenShotCard.fileName, text: text }); _context8.next = 14; return this.props.addFile(_nextFile); case 14: return _context8.abrupt('return', next); case 15: case 'end': return _context8.stop(); } } }, _callee8, this); })); function setCache(_x4, _x5) { return _ref9.apply(this, arguments); } return setCache; }() // 'capture' message をうけとったとき }, { key: 'uploadThumbnail', value: function () { var _ref10 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee9(data_url) { var body, response; return _regeneratorRuntime.wrap(function _callee9$(_context9) { while (1) { switch (_context9.prev = _context9.next) { case 0: body = new URLSearchParams(); body.append('data_url', data_url); _context9.next = 4; return fetch(organization.api.thumbnail, { method: 'POST', headers: { Accept: 'application/json', 'Content-Type': 'application/x-www-form-urlencoded' }, body: body.toString(), mode: 'cors' }); case 4: response = _context9.sent; if (!response.ok) { _context9.next = 11; break; } _context9.next = 8; return response.text(); case 8: return _context9.abrupt('return', _context9.sent); case 11: _context9.next = 13; return debugWindow(response); case 13: throw new Error(); case 14: case 'end': return _context9.stop(); } } }, _callee9, this); })); function uploadThumbnail(_x6) { return _ref10.apply(this, arguments); } return uploadThumbnail; }() }, { key: 'render', value: function render() { var _this3 = this; var _context$muiTheme = this.context.muiTheme, palette = _context$muiTheme.palette, paper = _context$muiTheme.paper, transitions = _context$muiTheme.transitions; var _state = this.state, selected = _state.selected, uploading = _state.uploading; var localization = this.props.localization; var styles = { root: { backgroundColor: fade(emphasize(palette.canvasColor, 1), 0.07), maxHeight: '50vh', overflowX: 'hidden', overflowY: 'scroll', padding: 8 }, action: { display: 'flex' }, blank: { flex: '1 1 auto' }, tile: function tile(hash) { return { zIndex: hash === selected ? 2 : 1, filter: hash === uploading ? 'blur(1px)' : 'blur(0px)', opacity: hash === uploading ? 0.5 : 1, overflow: hash === selected ? 'visible' : 'hidden', transition: transitions.easeOut() }; }, image: function image(file) { return { boxShadow: file === selected ? paper.zDepthShadows[1] : 'none', transition: transitions.easeOut() }; } }; var gridList = []; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { var _loop = function _loop() { var _step$value = _slicedToArray(_step.value, 2), hash = _step$value[0], url = _step$value[1]; gridList.push(React.createElement( GridTile, { key: hash, style: styles.tile(hash), onClick: function onClick(e) { return _this3.handleSelect(e, hash); } }, React.createElement('img', { style: styles.image(hash), src: url }) )); }; for (var _iterator = _getIterator(_Object$entries(this.state.cache)), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { _loop(); } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } var alreadySetImage = this.props.getConfig('ogp')['og:image'] === this.state.cache[selected]; return React.createElement( Card, _extends({ icon: ScreenShotCard.icon() }, this.props.cardPropsBag), React.createElement( GridList, { cellHeight: 180, style: styles.root, onClick: function onClick(event) { return _this3.handleSelect(event, null); } }, gridList ), React.createElement( CardActions, { style: styles.action }, React.createElement(FlatButton, { label: localization.screenShotCard.coverImage, disabled: !selected || alreadySetImage, onClick: this.handleThumbnailSet }), React.createElement('div', { style: styles.blank }), React.createElement(FlatButton, { label: '', icon: React.createElement(ActionDelete, null), disabled: !selected, onClick: this.handleThumbnailDelete }) ) ); } }, { key: 'search', get: function get() { try { var _ref11 = new URL(this.props.deployURL), pathname = _ref11.pathname; return pathname.split('/').pop(); } catch (e) { return null; } } }], [{ key: 'icon', value: function icon() { return React.createElement(ImagePhotoCamera, null); } }]); return ScreenShotCard; }(PureComponent); ScreenShotCard.propTypes = { cardPropsBag: PropTypes.object.isRequired, files: PropTypes.array.isRequired, findFile: PropTypes.func.isRequired, getConfig: PropTypes.func.isRequired, setConfig: PropTypes.func.isRequired, showNotice: PropTypes.func.isRequired, addFile: PropTypes.func.isRequired, putFile: PropTypes.func.isRequired, deployURL: PropTypes.string, localization: PropTypes.object.isRequired, updateCard: PropTypes.func.isRequired, globalEvent: PropTypes.object.isRequired }; ScreenShotCard.contextTypes = { muiTheme: PropTypes.object.isRequired }; ScreenShotCard.fileName = 'feeles/capture.json'; export default ScreenShotCard;