diff --git a/src/components/action-menu/icon--camera.svg b/src/components/action-menu/icon--camera.svg deleted file mode 100644 index e8c442d8f5d994a764942dcd957cff4239fde281..0000000000000000000000000000000000000000 Binary files a/src/components/action-menu/icon--camera.svg and /dev/null differ diff --git a/src/components/camera-modal/camera-modal.css b/src/components/camera-modal/camera-modal.css deleted file mode 100644 index 7522fbb2ec286f0491d62d1fd6a67a7ebb5b2ed4..0000000000000000000000000000000000000000 --- a/src/components/camera-modal/camera-modal.css +++ /dev/null @@ -1,157 +0,0 @@ -@import "../../css/colors.css"; -@import "../../css/units.css"; - -$main-button-size: 2.75rem; - -.modal-content { - width: 552px; -} - -.body { - display: flex; - flex-direction: column; - align-items: center; - background: $ui-white; - padding: 1.5rem 2.25rem; -} - -.camera-feed-container { - display: flex; - justify-content: space-around; - align-items: center; - - background: $ui-primary; - border: 1px solid $ui-black-transparent; - border-radius: 4px; - padding: 3px; - - width: 480px; - height: 360px; - position: relative; - overflow: hidden; -} - -.canvas { - position: absolute; - width: 480px; - height: 360px; -} - -.loading-text { - position: absolute; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - color: $text-primary-transparent; - font-size: 0.95rem; - font-weight: 500; - text-align: center; -} - -.help-text { - margin: 10px auto 0; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - color: $text-primary-transparent; - font-size: 0.95rem; - font-weight: 500; - text-align: center; -} - -.capture-text { - color: $motion-primary; -} - -.disabled-text { - color: $text-primary; - opacity: 0.25; -} - -.main-button-row { - display: flex; - flex-direction: column; - align-items: center; - justify-content: space-around; - margin-top: 15px; - width: 100%; -} - -/* Action Menu */ -.main-button { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - cursor: pointer; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - background: $motion-primary; - outline: none; - border: none; - transition: background-color 0.2s; - - border-radius: 100%; - width: $main-button-size; - height: $main-button-size; - box-shadow: 0 0 0 4px $motion-transparent; -} - -.main-button:hover { - background: $extensions-primary; - box-shadow: 0 0 0 6px $motion-transparent; -} - -.main-button:disabled { - background: $text-primary; - border-color: $ui-black-transparent; - box-shadow: none; - opacity: 0.25; -} - -.main-icon { - width: calc($main-button-size - 1rem); - height: calc($main-button-size - 1rem); -} - -.button-row { - font-weight: bolder; - text-align: right; - display: flex; - justify-content: space-between; - margin-top: 20px; - width: 480px; -} - -.button-row button { - padding: 0.75rem 1rem; - border-radius: 0.25rem; - background: $ui-white; - border: 1px solid $ui-black-transparent; - font-weight: 600; - font-size: 0.85rem; - color: $motion-primary; - cursor: pointer; -} - -.button-row button.ok-button { - background: $motion-primary; - border: $motion-primary; - color: $ui-white; -} - -[dir="rtl"] .retake-button img { - transform: scaleX(-1); -} - -@keyframes flash { - 0% { opacity: 1; } - 100% { opacity: 0; } -} - -.flash-overlay { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: $ui-white; - animation-name: flash; - animation-duration: 0.5s; - animation-fill-mode: forwards; /* Leave at 0 opacity after animation */ -} diff --git a/src/components/camera-modal/camera-modal.jsx b/src/components/camera-modal/camera-modal.jsx deleted file mode 100644 index 8c499c3624922e7d84ac1b00e75cf8f9205c29c0..0000000000000000000000000000000000000000 --- a/src/components/camera-modal/camera-modal.jsx +++ /dev/null @@ -1,141 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import {defineMessages, injectIntl, intlShape} from 'react-intl'; -import Box from '../box/box.jsx'; -import Modal from '../../containers/modal.jsx'; -import styles from './camera-modal.css'; -import backIcon from './icon--back.svg'; -import cameraIcon from '../action-menu/icon--camera.svg'; - -const messages = defineMessages({ - cameraModalTitle: { - defaultMessage: 'Take a Photo', - description: 'Title for prompt to take a picture (to add as a new costume).', - id: 'gui.cameraModal.cameraModalTitle' - }, - loadingCameraMessage: { - defaultMessage: 'Loading Camera...', - description: 'Notification to the user that the camera is loading', - id: 'gui.cameraModal.loadingCameraMessage' - }, - permissionRequest: { - defaultMessage: 'We need your permission to use your camera', - description: 'Notification to the user that the app needs camera access', - id: 'gui.cameraModal.permissionRequest' - }, - retakePhoto: { - defaultMessage: 'Retake Photo', - description: 'A button that allows the user to take the picture again, replacing the old one', - id: 'gui.cameraModal.retakePhoto' - }, - save: { - defaultMessage: 'Save', - description: 'A button that allows the user to save the photo they took as a costume', - id: 'gui.cameraModal.save' - }, - takePhotoButton: { - defaultMessage: 'Take Photo', - description: 'A button to take a photo', - id: 'gui.cameraModal.takePhoto' - }, - loadingCaption: { - defaultMessage: 'Loading...', - description: 'A caption for a disabled button while the video from the camera is still loading', - id: 'gui.cameraModal.loadingCaption' - }, - enableCameraCaption: { - defaultMessage: 'Enable Camera', - description: 'A caption for a disabled button prompting the user to enable camera access', - id: 'gui.cameraModal.enableCameraCaption' - } -}); - -const CameraModal = ({intl, ...props}) => ( - <Modal - className={styles.modalContent} - contentLabel={intl.formatMessage(messages.cameraModalTitle)} - onRequestClose={props.onCancel} - > - <Box className={styles.body}> - <Box className={styles.cameraFeedContainer}> - <div className={styles.loadingText}> - {props.access ? intl.formatMessage(messages.loadingCameraMessage) : - `â†–ï¸ \u00A0${intl.formatMessage(messages.permissionRequest)}`} - </div> - <canvas - className={styles.canvas} - // height and (below) width of the actual image - // double stage dimensions to avoid the need for - // resizing the captured image when importing costume - // to accommodate double resolution bitmaps - height="720" - ref={props.canvasRef} - width="960" - /> - {props.capture ? ( - <div className={styles.flashOverlay} /> - ) : null} - </Box> - {props.capture ? - <Box className={styles.buttonRow}> - <button - className={styles.retakeButton} - key="retake-button" - onClick={props.onBack} - > - <img - draggable={false} - src={backIcon} - /> {intl.formatMessage(messages.retakePhoto)} - </button> - <button - className={styles.okButton} - onClick={props.onSubmit} - > {intl.formatMessage(messages.save)} - </button> - </Box> : - <Box className={styles.mainButtonRow}> - <button - className={styles.mainButton} - disabled={!props.loaded} - key="capture-button" - onClick={props.onCapture} - > - <img - className={styles.mainIcon} - draggable={false} - src={cameraIcon} - /> - </button> - <div className={styles.helpText}> - {props.access ? - <span className={props.loaded ? styles.captureText : styles.disabledText}> - {props.loaded ? - intl.formatMessage(messages.takePhotoButton) : - intl.formatMessage(messages.loadingCaption)} - </span> : - <span className={styles.disabledText}> - {intl.formatMessage(messages.enableCameraCaption)} - </span> - } - </div> - - </Box> - } - </Box> - </Modal> -); - -CameraModal.propTypes = { - access: PropTypes.bool, - canvasRef: PropTypes.func.isRequired, - capture: PropTypes.string, - intl: intlShape.isRequired, - loaded: PropTypes.bool, - onBack: PropTypes.func.isRequired, - onCancel: PropTypes.func.isRequired, - onCapture: PropTypes.func.isRequired, - onSubmit: PropTypes.func.isRequired -}; - -export default injectIntl(CameraModal); diff --git a/src/components/camera-modal/icon--back.svg b/src/components/camera-modal/icon--back.svg deleted file mode 100644 index 47d09bc7fad766b50da3ed1cffec190b1e94878c..0000000000000000000000000000000000000000 Binary files a/src/components/camera-modal/icon--back.svg and /dev/null differ diff --git a/src/containers/camera-modal.jsx b/src/containers/camera-modal.jsx deleted file mode 100644 index c55b0ee450797d7d72e93343e7d5df4d6a7ceeda..0000000000000000000000000000000000000000 --- a/src/containers/camera-modal.jsx +++ /dev/null @@ -1,103 +0,0 @@ -import bindAll from 'lodash.bindall'; -import PropTypes from 'prop-types'; -import React from 'react'; -import {connect} from 'react-redux'; - -import CameraModalComponent from '../components/camera-modal/camera-modal.jsx'; -import ModalVideoManager from '../lib/video/modal-video-manager.js'; - -import { - closeCameraCapture -} from '../reducers/modals'; - -class CameraModal extends React.Component { - constructor (props) { - super(props); - bindAll(this, [ - 'handleAccess', - 'handleBack', - 'handleCancel', - 'handleCapture', - 'handleLoaded', - 'handleSubmit', - 'setCanvas' - ]); - - this.video = null; - this.videoDevice = null; - - this.state = { - capture: null, - access: false, - loaded: false - }; - } - componentWillUnmount () { - if (this.videoDevice) { - this.videoDevice.disableVideo(); - } - } - handleAccess () { - this.setState({access: true}); - } - handleLoaded () { - this.setState({loaded: true}); - } - handleBack () { - this.setState({capture: null}); - this.videoDevice.clearSnapshot(); - } - handleCapture () { - if (this.state.loaded) { - const capture = this.videoDevice.takeSnapshot(); - this.setState({capture: capture}); - } - } - setCanvas (canvas) { - this.canvas = canvas; - if (this.canvas) { - this.videoDevice = new ModalVideoManager(this.canvas); - this.videoDevice.enableVideo(this.handleAccess, this.handleLoaded); - } - } - handleSubmit () { - if (!this.state.capture) return; - this.props.onNewCostume(this.state.capture); - this.props.onClose(); - } - handleCancel () { - this.props.onClose(); - } - render () { - return ( - <CameraModalComponent - access={this.state.access} - canvasRef={this.setCanvas} - capture={this.state.capture} - loaded={this.state.loaded} - onBack={this.handleBack} - onCancel={this.handleCancel} - onCapture={this.handleCapture} - onSubmit={this.handleSubmit} - /> - ); - } -} - -CameraModal.propTypes = { - onClose: PropTypes.func, - onNewCostume: PropTypes.func -}; - -const mapStateToProps = () => ({}); - -const mapDispatchToProps = dispatch => ({ - onClose: () => { - dispatch(closeCameraCapture()); - } -}); - -export default connect( - mapStateToProps, - mapDispatchToProps -)(CameraModal); diff --git a/src/containers/costume-tab.jsx b/src/containers/costume-tab.jsx index f9ecdab08f5532881cd064a41df0e7fd3c50f58d..be9b6d44b15524dbd7f56d857c5f7ef8e724cf08 100644 --- a/src/containers/costume-tab.jsx +++ b/src/containers/costume-tab.jsx @@ -6,7 +6,6 @@ import VM from 'scratch-vm'; import AssetPanel from '../components/asset-panel/asset-panel.jsx'; import PaintEditorWrapper from './paint-editor-wrapper.jsx'; -import CameraModal from './camera-modal.jsx'; import {connect} from 'react-redux'; import {handleFileUpload, costumeUpload} from '../lib/file-uploader.js'; import errorBoundaryHOC from '../lib/error-boundary-hoc.jsx'; @@ -16,8 +15,6 @@ import sharedMessages from '../lib/shared-messages'; import downloadBlob from '../lib/download-blob'; import { - closeCameraCapture, - openCameraCapture, openCostumeLibrary, openBackdropLibrary } from '../reducers/modals'; @@ -34,7 +31,6 @@ import addLibraryBackdropIcon from '../components/asset-panel/icon--add-backdrop import addLibraryCostumeIcon from '../components/asset-panel/icon--add-costume-lib.svg'; import fileUploadIcon from '../components/action-menu/icon--file-upload.svg'; import paintIcon from '../components/action-menu/icon--paint.svg'; -import cameraIcon from '../components/action-menu/icon--camera.svg'; import surpriseIcon from '../components/action-menu/icon--surprise.svg'; import searchIcon from '../components/action-menu/icon--search.svg'; @@ -71,11 +67,6 @@ let messages = defineMessages({ defaultMessage: 'Upload Costume', description: 'Button to add a costume by uploading a file in the editor tab', id: 'gui.costumeTab.addFileCostume' - }, - addCameraCostumeMsg: { - defaultMessage: 'Camera', - description: 'Button to use the camera to create a costume costume in the editor tab', - id: 'gui.costumeTab.addCameraCostume' } }); @@ -95,7 +86,6 @@ class CostumeTab extends React.Component { 'handleSurpriseBackdrop', 'handleFileUploadClick', 'handleCostumeUpload', - 'handleCameraBuffer', 'handleDrop', 'setFileInput' ]); @@ -218,14 +208,6 @@ class CostumeTab extends React.Component { }, this.props.onCloseImporting); }, this.props.onCloseImporting); } - handleCameraBuffer (buffer) { - const storage = this.props.vm.runtime.storage; - const targetId = this.props.vm.editingTarget.id; - costumeUpload(buffer, 'image/png', storage, vmCostumes => { - vmCostumes[0].name = this.props.intl.formatMessage(messages.costume, {index: 1}); - this.handleNewCostume(vmCostumes, false, targetId); - }); - } handleFileUploadClick () { this.fileInput.click(); } @@ -264,11 +246,8 @@ class CostumeTab extends React.Component { dispatchUpdateRestore, // eslint-disable-line no-unused-vars intl, isRtl, - onNewCostumeFromCameraClick, onNewLibraryBackdropClick, onNewLibraryCostumeClick, - cameraModalVisible, - onRequestCloseCameraModal, vm } = this.props; @@ -299,11 +278,6 @@ class CostumeTab extends React.Component { img: addLibraryIcon, onClick: addLibraryFunc }, - { - title: intl.formatMessage(messages.addCameraCostumeMsg), - img: cameraIcon, - onClick: onNewCostumeFromCameraClick - }, { title: intl.formatMessage(addFileMessage), img: fileUploadIcon, @@ -346,29 +320,20 @@ class CostumeTab extends React.Component { /> : null } - {cameraModalVisible ? ( - <CameraModal - onClose={onRequestCloseCameraModal} - onNewCostume={this.handleCameraBuffer} - /> - ) : null} </AssetPanel> ); } } CostumeTab.propTypes = { - cameraModalVisible: PropTypes.bool, dispatchUpdateRestore: PropTypes.func, editingTarget: PropTypes.string, intl: intlShape, isRtl: PropTypes.bool, onActivateSoundsTab: PropTypes.func.isRequired, onCloseImporting: PropTypes.func.isRequired, - onNewCostumeFromCameraClick: PropTypes.func.isRequired, onNewLibraryBackdropClick: PropTypes.func.isRequired, onNewLibraryCostumeClick: PropTypes.func.isRequired, - onRequestCloseCameraModal: PropTypes.func.isRequired, onShowImporting: PropTypes.func.isRequired, sprites: PropTypes.shape({ id: PropTypes.shape({ @@ -392,8 +357,7 @@ const mapStateToProps = state => ({ isRtl: state.locales.isRtl, sprites: state.scratchGui.targets.sprites, stage: state.scratchGui.targets.stage, - dragging: state.scratchGui.assetDrag.dragging, - cameraModalVisible: state.scratchGui.modals.cameraCapture + dragging: state.scratchGui.assetDrag.dragging }); const mapDispatchToProps = dispatch => ({ @@ -406,12 +370,6 @@ const mapDispatchToProps = dispatch => ({ e.preventDefault(); dispatch(openCostumeLibrary()); }, - onNewCostumeFromCameraClick: () => { - dispatch(openCameraCapture()); - }, - onRequestCloseCameraModal: () => { - dispatch(closeCameraCapture()); - }, dispatchUpdateRestore: restoreState => { dispatch(setRestore(restoreState)); }, diff --git a/src/reducers/modals.js b/src/reducers/modals.js index 30381979051cc02ef6d3f20561007ea55c41d5df..2e69bf8ba752e5efbd53f7e10318f35a15f4ce8b 100644 --- a/src/reducers/modals.js +++ b/src/reducers/modals.js @@ -2,7 +2,6 @@ const OPEN_MODAL = 'scratch-gui/modals/OPEN_MODAL'; const CLOSE_MODAL = 'scratch-gui/modals/CLOSE_MODAL'; const MODAL_BACKDROP_LIBRARY = 'backdropLibrary'; -const MODAL_CAMERA_CAPTURE = 'cameraCapture'; const MODAL_COSTUME_LIBRARY = 'costumeLibrary'; const MODAL_EXTENSION_LIBRARY = 'extensionLibrary'; const MODAL_LOADING_PROJECT = 'loadingProject'; @@ -15,7 +14,6 @@ const MODAL_TIPS_LIBRARY = 'tipsLibrary'; const initialState = { [MODAL_BACKDROP_LIBRARY]: false, - [MODAL_CAMERA_CAPTURE]: false, [MODAL_COSTUME_LIBRARY]: false, [MODAL_EXTENSION_LIBRARY]: false, [MODAL_LOADING_PROJECT]: false, @@ -57,9 +55,6 @@ const closeModal = function (modal) { const openBackdropLibrary = function () { return openModal(MODAL_BACKDROP_LIBRARY); }; -const openCameraCapture = function () { - return openModal(MODAL_CAMERA_CAPTURE); -}; const openCostumeLibrary = function () { return openModal(MODAL_COSTUME_LIBRARY); }; @@ -90,9 +85,6 @@ const openTipsLibrary = function () { const closeBackdropLibrary = function () { return closeModal(MODAL_BACKDROP_LIBRARY); }; -const closeCameraCapture = function () { - return closeModal(MODAL_CAMERA_CAPTURE); -}; const closeCostumeLibrary = function () { return closeModal(MODAL_COSTUME_LIBRARY); }; @@ -124,7 +116,6 @@ export { reducer as default, initialState as modalsInitialState, openBackdropLibrary, - openCameraCapture, openCostumeLibrary, openExtensionLibrary, openLoadingProject, @@ -135,7 +126,6 @@ export { openTipsLibrary, openConnectionModal, closeBackdropLibrary, - closeCameraCapture, closeCostumeLibrary, closeExtensionLibrary, closeLoadingProject,