diff --git a/package.json b/package.json index 02c227df8ccd35562e7cb2750212ee0f683bcbb2..2d4bcf9b71c571c0bc8dca8a2677c7a64fec3798 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "scratch-audio": "0.1.0-prerelease.1523977528", "scratch-blocks": "0.1.0-prerelease.1524774938", "scratch-l10n": "2.0.20180108132626", - "scratch-paint": "0.2.0-prerelease.20180426161647", + "scratch-paint": "0.2.0-prerelease.20180426204040", "scratch-render": "0.1.0-prerelease.20180427143155", "scratch-svg-renderer": "0.1.0-prerelease.20180423193917", "scratch-storage": "0.4.0", diff --git a/src/components/cards/card.css b/src/components/cards/card.css new file mode 100644 index 0000000000000000000000000000000000000000..84b6e6bf784773577d29e29954b663d19f74ab5a --- /dev/null +++ b/src/components/cards/card.css @@ -0,0 +1,236 @@ +@import "../../css/units.css"; +@import "../../css/colors.css"; + +.card-container { + position:absolute; + z-index: 100; +} + +.left-card, .right-card { + height: 90%; + position: absolute; + top: 5%; + background: $ui-white; + border: 1px solid $ui-tertiary; + width: 10px; + z-index: 99; + opacity: 0.9; + overflow: hidden; +} + +.left-card { + left: -10px; + border-right: 0; + border-top-left-radius: 0.75rem; + border-bottom-left-radius: 0.75rem; +} + +.right-card { + right: -10px; + border-left: 0; + border-top-right-radius: 0.75rem; + border-bottom-right-radius: 0.75rem; +} + +.left-card::after, .right-card::after { + content: ""; + position: absolute; + top: 0; + left: 0; + height: 1.8rem; + width: 100%; + background: $motion-primary; +} + +.left-button, .right-button { + position: absolute; + top: 50%; + margin-top: -15px; + z-index: 101; + user-select: none; + cursor: pointer; + background: $motion-primary; + box-shadow: 0 0 0 4px $motion-transparent; + height: 40px; + width: 40px; + border-radius: 100%; + display: flex; + justify-content: center; + align-items: center; +} + +.left-button { + left: -27px; +} + +.right-button { + right: -27px; +} + +.card { + border: 1px solid $ui-tertiary; + border-radius: 0.75rem; + display: flex; + flex-direction: column; + cursor: move; + z-index: 101; + overflow: hidden; + box-shadow: 0px 5px 25px 5px $ui-black-transparent; + align-items: center; +} + +.header-buttons { + width: 100%; + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + background: $motion-primary; + border-bottom: 1px solid $motion-tertiary; + padding: 0.5rem; + font-size: 0.625rem; +} + +.remove-button, .all-button { + cursor: pointer; + color: white; + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; +} + +.step-title { + font-size: 0.9rem; + margin: 0.9rem; + text-align: center; + font-weight: bold; + color: $text-primary; +} + +.step-body { + background: $ui-white; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + position: relative; + text-align: center; +} + +.step-video { + height: 337px; +} + +.step-image { + max-width: 450px; + background: #F9F9F9; + border: 1px solid #ddd; + border-radius: 0.5rem; + overflow: hidden; + margin: 0 0.5rem 0.5rem; +} + +.decks { + display: flex; + flex-direction: row; + justify-content: space-around; + padding: 0 0.5rem 0.5rem; +} + +.deck { + display: flex; + flex-direction: column; + margin: 0 8px 8px; + cursor: pointer; + border: 1px solid $ui-black-transparent; + border-radius: 0.25rem; + overflow: hidden; +} + +.deck-image { + width: 130px; + height: 100px; + object-fit: cover; +} + +.deck-name { + color: $motion-primary; + font-weight: bold; + font-size: 0.85rem; + margin: 14px 0px; + text-align: center; + font-family: "Helvetica Neue"; + font-weight: bold; + text-align: center; +} + +.help-icon, .close-icon { + height: 0.75rem; +} + +.help-icon { + margin-right: 0.25rem; +} + +.close-icon { + margin-left: 0.25rem; + transform: rotate(45deg); +} + +.see-all { + display: flex; + flex-direction: row; + justify-content: center; + width: 100%; + padding: 0.5rem; +} + +.see-all-button { + cursor: pointer; + padding: 0.5rem 1rem; + background-color: $motion-primary; + color: white; + font-weight: bold; + border-radius: 0.25rem; + display: flex; + align-items: center; + color: $ui-white; + font-family: "Helvetica Neue"; + font-size: 12px; + font-weight: bold; + line-height: 15px; + text-align: center; +} + +.see-all-button img { + margin-left: 0.5rem; +} + +.video-cover { + width: 100%; + height: 100%; + position: absolute; + top: 0; + left: 0; +} + +.steps-list { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; +} + +.active-step-pip, .inactiveStepPip { + width: 0.5rem; + height: 0.5rem; + margin: 0 0.25rem; + border-radius: 100%; + background: transparent; + border: 2px solid $ui-white-transparent; +} + +.active-step-pip { + background: white; +} diff --git a/src/components/cards/cards.jsx b/src/components/cards/cards.jsx new file mode 100644 index 0000000000000000000000000000000000000000..ab01f8ecdf1f54a193abb692a38c0f00061e80b3 --- /dev/null +++ b/src/components/cards/cards.jsx @@ -0,0 +1,284 @@ +import PropTypes from 'prop-types'; +import React, {Fragment} from 'react'; +import {FormattedMessage} from 'react-intl'; +import Draggable from 'react-draggable'; + +import styles from './card.css'; + +import nextIcon from './icon--next.svg'; +import prevIcon from './icon--prev.svg'; + +import helpIcon from './icon--help.svg'; +import closeIcon from '../close-button/icon--close.svg'; + +const CardHeader = ({onCloseCards, onShowAll, totalSteps, step}) => ( + <div className={styles.headerButtons}> + <div + className={styles.allButton} + onClick={onShowAll} + > + <img + className={styles.helpIcon} + src={helpIcon} + /> + <FormattedMessage + defaultMessage="All How-Tos" + description="Title for button to return to how-to library" + id="gui.cards.all-how-tos" + /> + </div> + {totalSteps > 1 ? ( + <div className={styles.stepsList}> + {Array(totalSteps).fill(0) + .map((_, i) => ( + <div + className={i === step ? styles.activeStepPip : styles.inactiveStepPip} + key={`pip-step-${i}`} + /> + ))} + </div> + ) : null} + <div + className={styles.removeButton} + onClick={onCloseCards} + > + <FormattedMessage + defaultMessage="Remove" + description="Title for button to close how-to card" + id="gui.cards.remove" + /> + <img + className={styles.closeIcon} + src={closeIcon} + /> + </div> + </div> +); + +// Video step needs to know if the card is being dragged to cover the video +// so that the mouseup is not swallowed by the iframe. +const VideoStep = ({video, dragging}) => ( + <div className={styles.stepVideo}> + {dragging ? ( + <div className={styles.videoCover} /> + ) : null} + <iframe + allowFullScreen + allow="autoplay; encrypted-media" + frameBorder="0" + height="337" + src={`${video}?rel=0&showinfo=0`} + width="600" + /> + </div> +); + +VideoStep.propTypes = { + dragging: PropTypes.bool.isRequired, + video: PropTypes.string.isRequired +}; + +const ImageStep = ({title, image}) => ( + <Fragment> + <div className={styles.stepTitle}> + {title} + </div> + <div className={styles.stepImageContainer}> + <img + className={styles.stepImage} + draggable={false} + src={image} + /> + </div> + </Fragment> +); + +ImageStep.propTypes = { + image: PropTypes.string.isRequired, + title: PropTypes.node.isRequired +}; + +const NextPrevButtons = ({onNextStep, onPrevStep}) => ( + <Fragment> + {onNextStep ? ( + <div> + <div className={styles.rightCard} /> + <div + className={styles.rightButton} + onClick={onNextStep} + > + <img + draggable={false} + src={nextIcon} + /> + </div> + </div> + ) : null} + {onPrevStep ? ( + <div> + <div className={styles.leftCard} /> + <div + className={styles.leftButton} + onClick={onPrevStep} + > + <img + draggable={false} + src={prevIcon} + /> + </div> + </div> + ) : null} + </Fragment> +); + +NextPrevButtons.propTypes = { + onNextStep: PropTypes.func, + onPrevStep: PropTypes.func +}; +CardHeader.propTypes = { + onCloseCards: PropTypes.func.isRequired, + onShowAll: PropTypes.func.isRequired, + step: PropTypes.number, + totalSteps: PropTypes.number +}; + +const PreviewsStep = ({deckIds, content, onActivateDeckFactory, onShowAll}) => ( + <Fragment> + <div className={styles.stepTitle}> + <FormattedMessage + defaultMessage="More things to try!" + description="Title card with more things to try" + id="gui.cards.more-things-to-try" + /> + </div> + <div className={styles.decks}> + {deckIds.map(id => ( + <div + className={styles.deck} + key={`deck-preview-${id}`} + onClick={onActivateDeckFactory(id)} + > + <img + className={styles.deckImage} + draggable={false} + src={content[id].img} + /> + <div className={styles.deckName}>{content[id].name}</div> + </div> + ))} + </div> + <div className={styles.seeAll}> + <div + className={styles.seeAllButton} + onClick={onShowAll} + > + <FormattedMessage + defaultMessage="See more" + description="Title for button to see more in how-to library" + id="gui.cards.see-more" + /> + </div> + </div> + </Fragment> +); + +PreviewsStep.propTypes = { + content: PropTypes.shape({ + id: PropTypes.shape({ + name: PropTypes.node.isRequired, + img: PropTypes.string.isRequired, + steps: PropTypes.arrayOf(PropTypes.shape({ + title: PropTypes.node, + image: PropTypes.string, + video: PropTypes.string, + deckIds: PropTypes.arrayOf(PropTypes.string) + })) + }) + }).isRequired, + deckIds: PropTypes.arrayOf(PropTypes.string).isRequired, + onActivateDeckFactory: PropTypes.func.isRequired, + onShowAll: PropTypes.func.isRequired +}; + +const Cards = props => { + if (props.activeDeckId === null) return; + + const steps = props.content[props.activeDeckId].steps; + + return ( + <Draggable + bounds="parent" + position={{x: props.x, y: props.y}} + onDrag={props.onDrag} + onStart={props.onStartDrag} + onStop={props.onEndDrag} + > + <div className={styles.cardContainer}> + <div className={styles.card}> + <CardHeader + step={props.step} + totalSteps={steps.length} + onCloseCards={props.onCloseCards} + onShowAll={props.onShowAll} + /> + <div className={styles.stepBody}> + {steps[props.step].deckIds ? ( + <PreviewsStep + content={props.content} + deckIds={steps[props.step].deckIds} + onActivateDeckFactory={props.onActivateDeckFactory} + onShowAll={props.onShowAll} + /> + ) : ( + steps[props.step].video ? ( + <VideoStep + dragging={props.dragging} + video={steps[props.step].video} + /> + ) : ( + <ImageStep + image={steps[props.step].image} + title={steps[props.step].title} + /> + ) + )} + </div> + <NextPrevButtons + onNextStep={props.step < steps.length - 1 ? props.onNextStep : null} + onPrevStep={props.step > 0 ? props.onPrevStep : null} + /> + </div> + </div> + </Draggable> + ); +}; + +Cards.propTypes = { + activeDeckId: PropTypes.string.isRequired, + content: PropTypes.shape({ + id: PropTypes.shape({ + name: PropTypes.node.isRequired, + img: PropTypes.string.isRequired, + steps: PropTypes.arrayOf(PropTypes.shape({ + title: PropTypes.node, + image: PropTypes.string, + video: PropTypes.string, + deckIds: PropTypes.arrayOf(PropTypes.string) + })) + }) + }), + dragging: PropTypes.bool.isRequired, + onActivateDeckFactory: PropTypes.func.isRequired, + onCloseCards: PropTypes.func.isRequired, + onDrag: PropTypes.func, + onEndDrag: PropTypes.func, + onNextStep: PropTypes.func.isRequired, + onPrevStep: PropTypes.func.isRequired, + onShowAll: PropTypes.func, + onStartDrag: PropTypes.func, + step: PropTypes.number.isRequired, + x: PropTypes.number, + y: PropTypes.number +}; + +export default Cards; diff --git a/src/components/cards/icon--help.svg b/src/components/cards/icon--help.svg new file mode 100644 index 0000000000000000000000000000000000000000..436d052874bd47c11a55909be61d0fb83777c000 Binary files /dev/null and b/src/components/cards/icon--help.svg differ diff --git a/src/components/cards/icon--next.svg b/src/components/cards/icon--next.svg new file mode 100644 index 0000000000000000000000000000000000000000..0c991f7c6e4cb2e6ce3b85a13e2a84eff50f03f2 Binary files /dev/null and b/src/components/cards/icon--next.svg differ diff --git a/src/components/cards/icon--prev.svg b/src/components/cards/icon--prev.svg new file mode 100644 index 0000000000000000000000000000000000000000..82d4e886e115c47e1bec804e5c4dac60f7ae1171 Binary files /dev/null and b/src/components/cards/icon--prev.svg differ diff --git a/src/components/gui/gui.jsx b/src/components/gui/gui.jsx index 572d01bab1ffd3989d2e0a21275779ab9c7112f0..640e07fdd6d0af5b8d5fb20b14ffb490dda93313 100644 --- a/src/components/gui/gui.jsx +++ b/src/components/gui/gui.jsx @@ -17,8 +17,11 @@ import Stage from '../../containers/stage.jsx'; import Loader from '../loader/loader.jsx'; import Box from '../box/box.jsx'; import MenuBar from '../menu-bar/menu-bar.jsx'; + import PreviewModal from '../../containers/preview-modal.jsx'; import WebGlModal from '../../containers/webgl-modal.jsx'; +import TipsLibrary from '../../containers/tips-library.jsx'; +import Cards from '../../containers/cards.jsx'; import layout from '../../lib/layout-constants.js'; import styles from './gui.css'; @@ -44,6 +47,7 @@ const GUIComponent = props => { activeTabIndex, basePath, blocksTabVisible, + cardsVisible, children, costumesTabVisible, intl, @@ -54,6 +58,7 @@ const GUIComponent = props => { onActivateTab, previewInfoVisible, soundsTabVisible, + tipsLibraryVisible, vm, ...componentProps } = props; @@ -77,7 +82,6 @@ const GUIComponent = props => { if (isRendererSupported === null) { isRendererSupported = Renderer.isSupported(); } - return ( <Box className={styles.pageWrapper} @@ -92,6 +96,12 @@ const GUIComponent = props => { {isRendererSupported ? null : ( <WebGlModal /> )} + {tipsLibraryVisible ? ( + <TipsLibrary /> + ) : null} + {cardsVisible ? ( + <Cards /> + ) : null} <MenuBar /> <Box className={styles.bodyWrapper}> <Box className={styles.flexWrapper}> @@ -212,6 +222,7 @@ GUIComponent.propTypes = { activeTabIndex: PropTypes.number, basePath: PropTypes.string, blocksTabVisible: PropTypes.bool, + cardsVisible: PropTypes.bool, children: PropTypes.node, costumesTabVisible: PropTypes.bool, intl: intlShape.isRequired, @@ -223,6 +234,7 @@ GUIComponent.propTypes = { onTabSelect: PropTypes.func, previewInfoVisible: PropTypes.bool, soundsTabVisible: PropTypes.bool, + tipsLibraryVisible: PropTypes.bool, vm: PropTypes.instanceOf(VM).isRequired }; GUIComponent.defaultProps = { diff --git a/src/components/library-item/library-item.css b/src/components/library-item/library-item.css index f8874e0c4eea50664004c0f843191e2a75ee4da9..7b91cc96acf857c8957877fa73ab431f239385b9 100644 --- a/src/components/library-item/library-item.css +++ b/src/components/library-item/library-item.css @@ -71,7 +71,7 @@ .featured-item { flex-basis: 300px; max-width: 300px; - height: 320px; + height: auto; overflow: hidden; padding: 0; } @@ -87,11 +87,12 @@ .featured-text { font-weight: bold; padding: 10px; - height: 140px; + /* height: 140px; */ width: 300px; } .featured-description { + display: block; font-weight: normal; line-height: 2; } diff --git a/src/components/library-item/library-item.jsx b/src/components/library-item/library-item.jsx index 407cd6471b41435f7bdece4b0206bd5799cb3b64..8977d3f931d2069b805a8347ef887f69d78953e5 100644 --- a/src/components/library-item/library-item.jsx +++ b/src/components/library-item/library-item.jsx @@ -111,7 +111,10 @@ LibraryItem.propTypes = { featured: PropTypes.bool, iconURL: PropTypes.string.isRequired, id: PropTypes.number.isRequired, - name: PropTypes.string.isRequired, + name: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.node + ]).isRequired, onBlur: PropTypes.func, onFocus: PropTypes.func, onMouseEnter: PropTypes.func.isRequired, diff --git a/src/components/library/library.jsx b/src/components/library/library.jsx index e9996d4f2ea4716f35c650e713605aa803a5ff31..55303854055695efdc8371989815b1b87423ac3f 100644 --- a/src/components/library/library.jsx +++ b/src/components/library/library.jsx @@ -166,7 +166,10 @@ LibraryComponent.propTypes = { PropTypes.shape({ // @todo remove md5/rawURL prop from library, refactor to use storage md5: PropTypes.string, - name: PropTypes.string.isRequired, + name: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.node + ]).isRequired, rawURL: PropTypes.string }) /* eslint-enable react/no-unused-prop-types, lines-around-comment */ diff --git a/src/components/menu-bar/icon--help.svg b/src/components/menu-bar/icon--help.svg new file mode 100644 index 0000000000000000000000000000000000000000..6974a7f45f8c740074060a3414eadc02cefd0084 Binary files /dev/null and b/src/components/menu-bar/icon--help.svg differ diff --git a/src/components/menu-bar/menu-bar.css b/src/components/menu-bar/menu-bar.css index 1a26960a4581daece08d44e088419878e0644723..b46d08356a83c2c7c374f22831acd940dad318af 100644 --- a/src/components/menu-bar/menu-bar.css +++ b/src/components/menu-bar/menu-bar.css @@ -132,6 +132,12 @@ height: 1rem; } +.help-icon { + height: 2rem; + width: 3rem; + margin-top: 0.5rem; +} + .account-nav-menu, .mystuff-button { padding: 0 .25rem; display: flex; diff --git a/src/components/menu-bar/menu-bar.jsx b/src/components/menu-bar/menu-bar.jsx index f647b24df534aa6e96ee65917dc59b5b056a0cb7..16f7cfaf6e3be73ec2c67c3ecd565041c006b2e5 100644 --- a/src/components/menu-bar/menu-bar.jsx +++ b/src/components/menu-bar/menu-bar.jsx @@ -14,6 +14,7 @@ import Menu from '../../containers/menu.jsx'; import {MenuItem, MenuSection} from '../menu/menu.jsx'; import ProjectSaver from '../../containers/project-saver.jsx'; +import {openTipsLibrary} from '../../reducers/modals'; import { openFileMenu, closeFileMenu, @@ -31,6 +32,8 @@ import communityIcon from './icon--see-community.svg'; import dropdownCaret from '../language-selector/dropdown-caret.svg'; import scratchLogo from './scratch-logo.svg'; +import helpIcon from './icon--help.svg'; + const MenuBarItemTooltip = ({ children, className, @@ -220,6 +223,15 @@ const MenuBar = props => ( </div> </div> <div className={styles.accountInfoWrapper}> + <div + className={classNames(styles.menuBarItem, styles.hoverable)} + onClick={props.onOpenTipLibrary} + > + <img + className={styles.helpIcon} + src={helpIcon} + /> + </div> <MenuBarItemTooltip id="mystuff"> <div className={classNames( @@ -265,6 +277,7 @@ MenuBar.propTypes = { fileMenuOpen: PropTypes.bool, onClickEdit: PropTypes.func, onClickFile: PropTypes.func, + onOpenTipLibrary: PropTypes.func, onRequestCloseEdit: PropTypes.func, onRequestCloseFile: PropTypes.func }; @@ -275,6 +288,7 @@ const mapStateToProps = state => ({ }); const mapDispatchToProps = dispatch => ({ + onOpenTipLibrary: () => dispatch(openTipsLibrary()), onClickFile: () => dispatch(openFileMenu()), onRequestCloseFile: () => dispatch(closeFileMenu()), onClickEdit: () => dispatch(openEditMenu()), diff --git a/src/containers/cards.jsx b/src/containers/cards.jsx new file mode 100644 index 0000000000000000000000000000000000000000..3d08932f775894aa809014deb85b2cbaca78a93c --- /dev/null +++ b/src/containers/cards.jsx @@ -0,0 +1,46 @@ +import {connect} from 'react-redux'; + +import { + activateDeck, + closeCards, + nextStep, + prevStep, + dragCard, + startDrag, + endDrag +} from '../reducers/cards'; + +import { + openTipsLibrary +} from '../reducers/modals'; + +import CardsComponent from '../components/cards/cards.jsx'; + +const mapStateToProps = state => ({ + visible: state.cards.visible, + content: state.cards.content, + activeDeckId: state.cards.activeDeckId, + step: state.cards.step, + x: state.cards.x, + y: state.cards.y, + dragging: state.cards.dragging +}); + +const mapDispatchToProps = dispatch => ({ + onActivateDeckFactory: id => () => dispatch(activateDeck(id)), + onShowAll: () => { + dispatch(openTipsLibrary()); + dispatch(closeCards()); + }, + onCloseCards: () => dispatch(closeCards()), + onNextStep: () => dispatch(nextStep()), + onPrevStep: () => dispatch(prevStep()), + onDrag: (e_, data) => dispatch(dragCard(data.x, data.y)), + onStartDrag: () => dispatch(startDrag()), + onEndDrag: () => dispatch(endDrag()) +}); + +export default connect( + mapStateToProps, + mapDispatchToProps +)(CardsComponent); diff --git a/src/containers/gui.jsx b/src/containers/gui.jsx index cd2a5a95f76648e57b592e84f10a6e7ba16ca560..a47467c0c338a164ee1a38de1ce0ee7a99c3f24d 100644 --- a/src/containers/gui.jsx +++ b/src/containers/gui.jsx @@ -97,10 +97,12 @@ GUI.defaultProps = GUIComponent.defaultProps; const mapStateToProps = state => ({ activeTabIndex: state.editorTab.activeTabIndex, blocksTabVisible: state.editorTab.activeTabIndex === BLOCKS_TAB_INDEX, + cardsVisible: state.cards.visible, costumesTabVisible: state.editorTab.activeTabIndex === COSTUMES_TAB_INDEX, loadingStateVisible: state.modals.loadingProject, previewInfoVisible: state.modals.previewInfo, - soundsTabVisible: state.editorTab.activeTabIndex === SOUNDS_TAB_INDEX + soundsTabVisible: state.editorTab.activeTabIndex === SOUNDS_TAB_INDEX, + tipsLibraryVisible: state.modals.tipsLibrary }); const mapDispatchToProps = dispatch => ({ diff --git a/src/containers/tips-library.jsx b/src/containers/tips-library.jsx new file mode 100644 index 0000000000000000000000000000000000000000..7d45f37a6c967aa2ff669464bc41042aee768da7 --- /dev/null +++ b/src/containers/tips-library.jsx @@ -0,0 +1,75 @@ +import bindAll from 'lodash.bindall'; +import PropTypes from 'prop-types'; +import React from 'react'; + +import decksLibraryContent from '../lib/libraries/decks/index.jsx'; + +import analytics from '../lib/analytics'; +import LibraryComponent from '../components/library/library.jsx'; + +import {connect} from 'react-redux'; + +import { + closeTipsLibrary +} from '../reducers/modals'; + +import { + activateDeck +} from '../reducers/cards'; + +class TipsLibrary extends React.PureComponent { + constructor (props) { + super(props); + bindAll(this, [ + 'handleItemSelect' + ]); + } + handleItemSelect (item) { + this.props.onActivateDeck(item.id); + analytics.event({ + category: 'library', + action: 'Select How-to', + label: item.id + }); + } + render () { + const decksLibraryThumbnailData = Object.keys(decksLibraryContent).map(id => ({ + rawURL: decksLibraryContent[id].img, + id: id, + name: decksLibraryContent[id].name, + featured: true + })); + + if (!this.props.visible) return null; + return ( + <LibraryComponent + data={decksLibraryThumbnailData} + filterable={false} + title="How-Tos" + visible={this.props.visible} + onItemSelected={this.handleItemSelect} + onRequestClose={this.props.onRequestClose} + /> + ); + } +} + +TipsLibrary.propTypes = { + onActivateDeck: PropTypes.func.isRequired, + onRequestClose: PropTypes.func, + visible: PropTypes.bool +}; + +const mapStateToProps = state => ({ + visible: state.modals.tipsLibrary +}); + +const mapDispatchToProps = dispatch => ({ + onActivateDeck: id => dispatch(activateDeck(id)), + onRequestClose: () => dispatch(closeTipsLibrary()) +}); + +export default connect( + mapStateToProps, + mapDispatchToProps +)(TipsLibrary); diff --git a/src/lib/libraries/decks/clicker/add-sound.gif b/src/lib/libraries/decks/clicker/add-sound.gif new file mode 100644 index 0000000000000000000000000000000000000000..16408bed591f8359bbe2139a9d6fffd7a56a6fa5 Binary files /dev/null and b/src/lib/libraries/decks/clicker/add-sound.gif differ diff --git a/src/lib/libraries/decks/clicker/add-whenclicked.gif b/src/lib/libraries/decks/clicker/add-whenclicked.gif new file mode 100644 index 0000000000000000000000000000000000000000..a03b3d14e4b34f6bf1ba52ce8112b6a85019b7b0 Binary files /dev/null and b/src/lib/libraries/decks/clicker/add-whenclicked.gif differ diff --git a/src/lib/libraries/decks/clicker/click-events.gif b/src/lib/libraries/decks/clicker/click-events.gif new file mode 100644 index 0000000000000000000000000000000000000000..b387b01e31ba78e9b34d5dd8b4d2c46b407de35d Binary files /dev/null and b/src/lib/libraries/decks/clicker/click-events.gif differ diff --git a/src/lib/libraries/decks/clicker/click-goto.gif b/src/lib/libraries/decks/clicker/click-goto.gif new file mode 100644 index 0000000000000000000000000000000000000000..7be32f5c4f4d955f39538a1e254023fd1aece7c4 Binary files /dev/null and b/src/lib/libraries/decks/clicker/click-goto.gif differ diff --git a/src/lib/libraries/decks/clicker/click-sprite.gif b/src/lib/libraries/decks/clicker/click-sprite.gif new file mode 100644 index 0000000000000000000000000000000000000000..955a39c9c78f74d961b9b5feb6825473856c247c Binary files /dev/null and b/src/lib/libraries/decks/clicker/click-sprite.gif differ diff --git a/src/lib/libraries/decks/clicker/drag-goto.gif b/src/lib/libraries/decks/clicker/drag-goto.gif new file mode 100644 index 0000000000000000000000000000000000000000..1e24802e939d0e53ff81b42f93f2c84b56b76d2a Binary files /dev/null and b/src/lib/libraries/decks/clicker/drag-goto.gif differ diff --git a/src/lib/libraries/decks/clicker/library-clicker.gif b/src/lib/libraries/decks/clicker/library-clicker.gif new file mode 100644 index 0000000000000000000000000000000000000000..bc0e2d1934fb1dc91433982237e8088a04ce2f98 Binary files /dev/null and b/src/lib/libraries/decks/clicker/library-clicker.gif differ diff --git a/src/lib/libraries/decks/clicker/thumb-clicker.gif b/src/lib/libraries/decks/clicker/thumb-clicker.gif new file mode 100644 index 0000000000000000000000000000000000000000..ca46a4b7bce9e67cf86472bff54feacb33c06841 Binary files /dev/null and b/src/lib/libraries/decks/clicker/thumb-clicker.gif differ diff --git a/src/lib/libraries/decks/index.jsx b/src/lib/libraries/decks/index.jsx new file mode 100644 index 0000000000000000000000000000000000000000..d831c5f7380829bb2427bd8a0eda5b0c534befb9 --- /dev/null +++ b/src/lib/libraries/decks/index.jsx @@ -0,0 +1,411 @@ +import React from 'react'; +import {FormattedMessage} from 'react-intl'; + +// Spin around +import librarySpin from './spin/library-spin.gif'; +import stepDragTurn from './spin/drag-turn.gif'; +import stepClickTurn from './spin/click-turn.gif'; +import stepClickControl from './spin/click-control.gif'; +import stepDragForever from './spin/drag-forever.gif'; +import stepClickForever from './spin/click-forever.gif'; +import stepChangeColor from './spin/change-color.gif'; + +// Say hello +import librarySay from './say/library-say.gif'; +import stepAddSprite from './say/add-sprite.gif'; +import stepClickLooks from './say/click-looks.gif'; +import stepDragSay from './say/drag-say.gif'; +import stepClickSay from './say/click-say.gif'; +import stepAnotherSay from './say/another-say.gif'; +import stepEditSay from './say/edit-say.gif'; +import stepClickStack from './say/click-stack.gif'; + +// Clicker +import libraryClicker from './clicker/library-clicker.gif'; +import stepDragGoTo from './clicker/drag-goto.gif'; +import stepClickGoTo from './clicker/click-goto.gif'; +import stepClickEvents from './clicker/click-events.gif'; +import stepAddWhenClicked from './clicker/add-whenclicked.gif'; +import stepClickSprite from './clicker/click-sprite.gif'; +import stepAddSound from './clicker/add-sound.gif'; + +// Videos +import glideAroundThumb from './videos/glide-around.jpg'; +import changeSizeThumb from './videos/change-size.jpg'; +import switchCostumeThumb from './videos/switch-costume.jpg'; +import hideAndShowThumb from './videos/hide-and-show.jpg'; +import addBackdropThumb from './videos/add-backdrop.jpg'; +import addEffectsThumb from './videos/add-effects.jpg'; +import moveArrowKeysThumb from './videos/move-arrow-keys.jpg'; +import spinThumb from './videos/spin.jpg'; + +export default { + 'spin-around': { + name: ( + <FormattedMessage + defaultMessage="Spin around" + description="Name for the 'Spin around' how-to" + id="gui.howtos.spin-around.name" + /> + ), + img: librarySpin, + steps: [ + { + title: ( + <FormattedMessage + defaultMessage="Drag out a “turn” block" + description="Step name for 'Drag out a “turn” block' step" + id="gui.howtos.spin.step_dragTurn" + /> + ), + image: stepDragTurn + }, { + title: ( + <FormattedMessage + defaultMessage="Click the block to run it" + description="Step name for 'Click the block to run it' step" + id="gui.howtos.spin.step_clickTurn" + /> + ), + image: stepClickTurn + }, { + title: ( + <FormattedMessage + defaultMessage="Click the “Control” category" + description="Step name for 'Click the “Control” category' step" + id="gui.howtos.spin.step_clickControl" + /> + ), + image: stepClickControl + }, { + title: ( + <FormattedMessage + defaultMessage="Drag out a “forever” block" + description="Step name for 'Drag out a “forever” block' step" + id="gui.howtos.spin.step_dragForever" + /> + ), + image: stepDragForever + }, { + title: ( + <FormattedMessage + defaultMessage="Click the stack to run it" + description="Step name for 'Click the stack to run it' step" + id="gui.howtos.spin.step_clickForever" + /> + ), + image: stepClickForever + }, { + title: ( + <FormattedMessage + defaultMessage="Add a “change color effect” block" + description="Step name for 'Add a “change color effect” block' step" + id="gui.howtos.spin.step_changeColor" + /> + ), + image: stepChangeColor + }, { + deckIds: [ + 'add-a-backdrop', + 'switch-costume', + 'change-size' + ] + } + ] + }, + 'say-hello': { + name: ( + <FormattedMessage + defaultMessage="Say hello" + description="Name for the 'Say hello' how-to" + id="gui.howtos.say-hello.name" + /> + ), + img: librarySay, + steps: [ + { + title: ( + <FormattedMessage + defaultMessage="Add a new sprite" + description="Step name for 'Add a new sprite' step" + id="gui.howtos.say-hello.step_addSprite" + /> + ), + image: stepAddSprite + }, { + title: ( + <FormattedMessage + defaultMessage="Click the “Looks” category" + description="Step name for 'Click the “Looks” category' step" + id="gui.howtos.say-hello.step_clickLooks" + /> + ), + image: stepClickLooks + }, { + title: ( + <FormattedMessage + defaultMessage="Drag out a “say” block" + description="Step name for 'Drag out a “say” block' step" + id="gui.howtos.say-hello.step_dragSay" + /> + ), + image: stepDragSay + }, { + title: ( + <FormattedMessage + defaultMessage="Click the block to run it" + description="Step name for 'Click the block to run it' step" + id="gui.howtos.say-hello.step_clickSay" + /> + ), + image: stepClickSay + }, { + title: ( + <FormattedMessage + defaultMessage="Drag out another “say” block" + description="Step name for 'Drag out another “say” block' step" + id="gui.howtos.say-hello.step_anotherSay" + /> + ), + image: stepAnotherSay + }, { + title: ( + <FormattedMessage + defaultMessage="Say something else" + description="Step name for 'Say something else' step" + id="gui.howtos.say-hello.step_editSay" + /> + ), + image: stepEditSay + }, { + title: ( + <FormattedMessage + defaultMessage="Click the stack to run it" + description="Step name for 'Click the stack to run it' step" + id="gui.howtos.say-hello.step_clickStack" + /> + ), + image: stepClickStack + }, { + deckIds: [ + 'add-a-backdrop', + 'switch-costume', + 'change-size' + ] + } + ] + }, + 'run-away': { + name: ( + <FormattedMessage + defaultMessage="Run away" + description="Name for the 'Run away' how-to" + id="gui.howtos.run-away.name" + /> + ), + img: libraryClicker, + steps: [ + { + title: ( + <FormattedMessage + defaultMessage="Drag out a “go to random position” block" + description="Step name for 'Drag out a “go to random position” block' step" + id="gui.howtos.run-away.step_dragGoTo" + /> + ), + image: stepDragGoTo + }, { + title: ( + <FormattedMessage + defaultMessage="Click the block to run it" + description="Step name for 'Click the block to run it' step" + id="gui.howtos.run-away.step_clickGoTo" + /> + ), + image: stepClickGoTo + }, { + title: ( + <FormattedMessage + defaultMessage="Click the “Events” category" + description="Step 3 title" + id="gui.howtos.run-away.step3" + /> + ), + image: stepClickEvents + }, { + title: ( + <FormattedMessage + defaultMessage="Add a “when this sprite clicked” block" + description="Step name for 'Add a “when this sprite clicked” block' step" + id="gui.howtos.run-away.step_addWhenClicked" + /> + ), + image: stepAddWhenClicked + }, { + title: ( + <FormattedMessage + defaultMessage="Click the sprite to run it" + description="Step name for 'Click the sprite to run it' step" + id="gui.howtos.run-away.step_clickSprite" + /> + ), + image: stepClickSprite + }, { + title: ( + <FormattedMessage + defaultMessage="Add a “start sound” block" + description="Step name for 'Add a “start sound” block' step" + id="gui.howtos.run-away.step_addSound" + /> + ), + image: stepAddSound + }, { + deckIds: [ + 'add-a-backdrop', + 'switch-costume', + 'change-size' + ] + } + ] + }, + 'glide-around': { + name: ( + <FormattedMessage + defaultMessage="Glide around" + description="Name for the 'Glide around' how-to" + id="gui.howtos.glide-around.name" + /> + ), + img: glideAroundThumb, + steps: [{ + video: 'https://www.youtube.com/embed/WUcmsMEIbGg' + }, { + deckIds: [ + 'add-a-backdrop', + 'switch-costume', + 'change-size' + ] + }] + }, + 'change-size': { + name: ( + <FormattedMessage + defaultMessage="Change size" + description="Name for the 'Change size' how-to" + id="gui.howtos.change-size.name" + /> + ), + img: changeSizeThumb, + steps: [{ + video: 'https://www.youtube.com/embed/NiK9KcghZ9s' + }, { + deckIds: [ + 'add-a-backdrop', + 'switch-costume', + 'change-size' + ] + }] + }, + 'switch-costume': { + name: ( + <FormattedMessage + defaultMessage="Switch costume" + description="Name for the 'Switch costume' how-to" + id="gui.howtos.switch-costume.name" + /> + ), + img: switchCostumeThumb, + steps: [{ + video: 'https://www.youtube.com/embed/AUBoFxQDPWA' + }, { + deckIds: [ + 'add-a-backdrop', + 'switch-costume', + 'change-size' + ] + }] + }, + 'hide-and-show': { + name: ( + <FormattedMessage + defaultMessage="Hide & Show" + description="Name for the 'Hide & Show' how-to" + id="gui.howtos.hide-and-show.name" + /> + ), + img: hideAndShowThumb, + steps: [{ + video: 'https://www.youtube.com/embed/jpvqnlfsDTU' + }, { + deckIds: [ + 'add-a-backdrop', + 'switch-costume', + 'change-size' + ] + }] + }, + 'add-a-backdrop': { + name: ( + <FormattedMessage + defaultMessage="Add a backdrop" + description="Name for the 'Add a backdrop' how-to" + id="gui.howtos.add-a-backdrop.name" + /> + ), + img: addBackdropThumb, + steps: [{ + video: 'https://www.youtube.com/embed/WpV05Q7AbPU' + }, { + deckIds: [ + 'add-a-backdrop', + 'switch-costume', + 'change-size' + ] + }] + }, + 'add-effects': { + name: ( + <FormattedMessage + defaultMessage="Add effects" + description="Name for the 'Add effects' how-to" + id="gui.howtos.add-effects.name" + /> + ), + img: addEffectsThumb, + steps: [{ + video: 'https://www.youtube.com/embed/ORuohhkx15g' + }, { + deckIds: [ + 'add-a-backdrop', + 'switch-costume', + 'change-size' + ] + }] + }, + 'move-around-with-arrow-keys': { + name: 'Move Using Arrow Keys', + img: moveArrowKeysThumb, + steps: [{ + video: 'https://www.youtube.com/embed/7DUA_Yl0B_M' + }, { + deckIds: [ + 'add-a-backdrop', + 'switch-costume', + 'change-size' + ] + }] + }, + 'spin-video': { + name: 'Spin!', + img: spinThumb, + steps: [{ + video: 'https://www.youtube.com/embed/rHP3aojB_6w' + }, { + deckIds: [ + 'add-a-backdrop', + 'switch-costume', + 'change-size' + ] + }] + } +}; diff --git a/src/lib/libraries/decks/intro/add-glide.gif b/src/lib/libraries/decks/intro/add-glide.gif new file mode 100644 index 0000000000000000000000000000000000000000..9341cd30fe510f61c47d98a1f4c1276731307164 Binary files /dev/null and b/src/lib/libraries/decks/intro/add-glide.gif differ diff --git a/src/lib/libraries/decks/intro/add-say.gif b/src/lib/libraries/decks/intro/add-say.gif new file mode 100644 index 0000000000000000000000000000000000000000..55e370e68fde62ff368a0bb463b799a72a93986d Binary files /dev/null and b/src/lib/libraries/decks/intro/add-say.gif differ diff --git a/src/lib/libraries/decks/intro/drag-glide.gif b/src/lib/libraries/decks/intro/drag-glide.gif new file mode 100644 index 0000000000000000000000000000000000000000..939ada9fd076552e433cb2f4092c23dc3ca0d476 Binary files /dev/null and b/src/lib/libraries/decks/intro/drag-glide.gif differ diff --git a/src/lib/libraries/decks/intro/drag-say.gif b/src/lib/libraries/decks/intro/drag-say.gif new file mode 100644 index 0000000000000000000000000000000000000000..e6546012f746c2b8189d21790271cfd47bd12871 Binary files /dev/null and b/src/lib/libraries/decks/intro/drag-say.gif differ diff --git a/src/lib/libraries/decks/intro/hat-stack.gif b/src/lib/libraries/decks/intro/hat-stack.gif new file mode 100644 index 0000000000000000000000000000000000000000..6e4dc77b0cd8914f176a132dfd52a25ead0d8378 Binary files /dev/null and b/src/lib/libraries/decks/intro/hat-stack.gif differ diff --git a/src/lib/libraries/decks/intro/when-clicked.gif b/src/lib/libraries/decks/intro/when-clicked.gif new file mode 100644 index 0000000000000000000000000000000000000000..ab390154f4d16f5a9577074c7e185f9ed7fcc664 Binary files /dev/null and b/src/lib/libraries/decks/intro/when-clicked.gif differ diff --git a/src/lib/libraries/decks/say/add-sprite.gif b/src/lib/libraries/decks/say/add-sprite.gif new file mode 100644 index 0000000000000000000000000000000000000000..efcb8a3d556946a2b19f40dfbe33f084997d0da9 Binary files /dev/null and b/src/lib/libraries/decks/say/add-sprite.gif differ diff --git a/src/lib/libraries/decks/say/another-say.gif b/src/lib/libraries/decks/say/another-say.gif new file mode 100644 index 0000000000000000000000000000000000000000..842f93b343273c0f9c8a032be03094d1644567a0 Binary files /dev/null and b/src/lib/libraries/decks/say/another-say.gif differ diff --git a/src/lib/libraries/decks/say/click-looks.gif b/src/lib/libraries/decks/say/click-looks.gif new file mode 100644 index 0000000000000000000000000000000000000000..a2bf3165319db11b9cba798808b38c3f82b031a1 Binary files /dev/null and b/src/lib/libraries/decks/say/click-looks.gif differ diff --git a/src/lib/libraries/decks/say/click-say.gif b/src/lib/libraries/decks/say/click-say.gif new file mode 100644 index 0000000000000000000000000000000000000000..8ed7b817a91fcd98893f0c0e58e8e9dacf8a9a34 Binary files /dev/null and b/src/lib/libraries/decks/say/click-say.gif differ diff --git a/src/lib/libraries/decks/say/click-stack.gif b/src/lib/libraries/decks/say/click-stack.gif new file mode 100644 index 0000000000000000000000000000000000000000..bb427e586c84b783bae8b1fd99114d8f1fe376c8 Binary files /dev/null and b/src/lib/libraries/decks/say/click-stack.gif differ diff --git a/src/lib/libraries/decks/say/drag-say.gif b/src/lib/libraries/decks/say/drag-say.gif new file mode 100644 index 0000000000000000000000000000000000000000..5597bc9792a145e2cf242ec5380f36a273958caa Binary files /dev/null and b/src/lib/libraries/decks/say/drag-say.gif differ diff --git a/src/lib/libraries/decks/say/edit-say.gif b/src/lib/libraries/decks/say/edit-say.gif new file mode 100644 index 0000000000000000000000000000000000000000..03076cda1d2dc0731e37d788d3341144635999cc Binary files /dev/null and b/src/lib/libraries/decks/say/edit-say.gif differ diff --git a/src/lib/libraries/decks/say/library-say.gif b/src/lib/libraries/decks/say/library-say.gif new file mode 100644 index 0000000000000000000000000000000000000000..45e6ebbafb8a72108377d890493055c1a8cf6ac6 Binary files /dev/null and b/src/lib/libraries/decks/say/library-say.gif differ diff --git a/src/lib/libraries/decks/say/thumb-say.gif b/src/lib/libraries/decks/say/thumb-say.gif new file mode 100644 index 0000000000000000000000000000000000000000..279017d1d2a20b9ef6a1abdf93488043ae082855 Binary files /dev/null and b/src/lib/libraries/decks/say/thumb-say.gif differ diff --git a/src/lib/libraries/decks/spin/change-color.gif b/src/lib/libraries/decks/spin/change-color.gif new file mode 100644 index 0000000000000000000000000000000000000000..dca51dad4e1c4b8de89436c025ce38d0f03c45c4 Binary files /dev/null and b/src/lib/libraries/decks/spin/change-color.gif differ diff --git a/src/lib/libraries/decks/spin/click-control.gif b/src/lib/libraries/decks/spin/click-control.gif new file mode 100644 index 0000000000000000000000000000000000000000..24128a0edd07854a4415e0c467d273558b70afa5 Binary files /dev/null and b/src/lib/libraries/decks/spin/click-control.gif differ diff --git a/src/lib/libraries/decks/spin/click-forever.gif b/src/lib/libraries/decks/spin/click-forever.gif new file mode 100644 index 0000000000000000000000000000000000000000..f9d465bc093cb70428ad09e1db37ba2b78057977 Binary files /dev/null and b/src/lib/libraries/decks/spin/click-forever.gif differ diff --git a/src/lib/libraries/decks/spin/click-turn.gif b/src/lib/libraries/decks/spin/click-turn.gif new file mode 100644 index 0000000000000000000000000000000000000000..af887244849f335a7b29b0abbcac2b96f2db0ef9 Binary files /dev/null and b/src/lib/libraries/decks/spin/click-turn.gif differ diff --git a/src/lib/libraries/decks/spin/drag-forever.gif b/src/lib/libraries/decks/spin/drag-forever.gif new file mode 100644 index 0000000000000000000000000000000000000000..a51d6b4385d2d4d45d6bc15aca2913f0c4f9b6bc Binary files /dev/null and b/src/lib/libraries/decks/spin/drag-forever.gif differ diff --git a/src/lib/libraries/decks/spin/drag-turn.gif b/src/lib/libraries/decks/spin/drag-turn.gif new file mode 100644 index 0000000000000000000000000000000000000000..8df663eaf9316622017ee86a8d100750e97670f4 Binary files /dev/null and b/src/lib/libraries/decks/spin/drag-turn.gif differ diff --git a/src/lib/libraries/decks/spin/library-spin.gif b/src/lib/libraries/decks/spin/library-spin.gif new file mode 100644 index 0000000000000000000000000000000000000000..12e60ecf79b543f77a9840fa687a903d69c3db32 Binary files /dev/null and b/src/lib/libraries/decks/spin/library-spin.gif differ diff --git a/src/lib/libraries/decks/spin/thumb-spin.gif b/src/lib/libraries/decks/spin/thumb-spin.gif new file mode 100644 index 0000000000000000000000000000000000000000..e151455be735a0a8a65af10a2c85691ff66790f1 Binary files /dev/null and b/src/lib/libraries/decks/spin/thumb-spin.gif differ diff --git a/src/lib/libraries/decks/story/add-say--zoomed.gif b/src/lib/libraries/decks/story/add-say--zoomed.gif new file mode 100644 index 0000000000000000000000000000000000000000..2e8470164efa68433d84746e7c5592c1feaa5732 Binary files /dev/null and b/src/lib/libraries/decks/story/add-say--zoomed.gif differ diff --git a/src/lib/libraries/decks/story/add-say.gif b/src/lib/libraries/decks/story/add-say.gif new file mode 100644 index 0000000000000000000000000000000000000000..bdf5b7aa697a68936d92a1b8c246effc3512fde0 Binary files /dev/null and b/src/lib/libraries/decks/story/add-say.gif differ diff --git a/src/lib/libraries/decks/story/add-sprite--zoomed.gif b/src/lib/libraries/decks/story/add-sprite--zoomed.gif new file mode 100644 index 0000000000000000000000000000000000000000..38d846634fc47e30320d69fe5c20f6d85259270b Binary files /dev/null and b/src/lib/libraries/decks/story/add-sprite--zoomed.gif differ diff --git a/src/lib/libraries/decks/story/add-sprite.gif b/src/lib/libraries/decks/story/add-sprite.gif new file mode 100644 index 0000000000000000000000000000000000000000..ab2735208c992b29e265ab66bdedce13b49c0636 Binary files /dev/null and b/src/lib/libraries/decks/story/add-sprite.gif differ diff --git a/src/lib/libraries/decks/story/add-wait--zoomed.gif b/src/lib/libraries/decks/story/add-wait--zoomed.gif new file mode 100644 index 0000000000000000000000000000000000000000..b6c1a3562823d3522bbc7ade77cb2f227ed74f95 Binary files /dev/null and b/src/lib/libraries/decks/story/add-wait--zoomed.gif differ diff --git a/src/lib/libraries/decks/story/add-wait.gif b/src/lib/libraries/decks/story/add-wait.gif new file mode 100644 index 0000000000000000000000000000000000000000..ba5701c251d01e5fd94a5503c45e4a263ba3a452 Binary files /dev/null and b/src/lib/libraries/decks/story/add-wait.gif differ diff --git a/src/lib/libraries/decks/story/another-say--zoomed.gif b/src/lib/libraries/decks/story/another-say--zoomed.gif new file mode 100644 index 0000000000000000000000000000000000000000..2cd8124409994fcc29de581e840393cdabcff9f2 Binary files /dev/null and b/src/lib/libraries/decks/story/another-say--zoomed.gif differ diff --git a/src/lib/libraries/decks/story/another-say.gif b/src/lib/libraries/decks/story/another-say.gif new file mode 100644 index 0000000000000000000000000000000000000000..7a5e09b6c857d5e83ecf6f7829968031a804a79d Binary files /dev/null and b/src/lib/libraries/decks/story/another-say.gif differ diff --git a/src/lib/libraries/decks/story/both-say.gif b/src/lib/libraries/decks/story/both-say.gif new file mode 100644 index 0000000000000000000000000000000000000000..5cce6ad3c8c459303ea84e631709ae0a712b06cc Binary files /dev/null and b/src/lib/libraries/decks/story/both-say.gif differ diff --git a/src/lib/libraries/decks/story/click-say.gif b/src/lib/libraries/decks/story/click-say.gif new file mode 100644 index 0000000000000000000000000000000000000000..02fa02b0f558f906d5b1f58f98809ed808a14660 Binary files /dev/null and b/src/lib/libraries/decks/story/click-say.gif differ diff --git a/src/lib/libraries/decks/story/dialog.gif b/src/lib/libraries/decks/story/dialog.gif new file mode 100644 index 0000000000000000000000000000000000000000..b89ab96a4b95fc11322083060b234595f6032566 Binary files /dev/null and b/src/lib/libraries/decks/story/dialog.gif differ diff --git a/src/lib/libraries/decks/story/green-flag--zoomed.gif b/src/lib/libraries/decks/story/green-flag--zoomed.gif new file mode 100644 index 0000000000000000000000000000000000000000..18b1ec2b846f8d50d801a63cd239992b1ed07637 Binary files /dev/null and b/src/lib/libraries/decks/story/green-flag--zoomed.gif differ diff --git a/src/lib/libraries/decks/story/green-flag.gif b/src/lib/libraries/decks/story/green-flag.gif new file mode 100644 index 0000000000000000000000000000000000000000..aea1e74266188c541a476a1d8b34629249eb945e Binary files /dev/null and b/src/lib/libraries/decks/story/green-flag.gif differ diff --git a/src/lib/libraries/decks/story/sprite-library.gif b/src/lib/libraries/decks/story/sprite-library.gif new file mode 100644 index 0000000000000000000000000000000000000000..51a6738dc351fe2eea0ebae1cbe135370e39befc Binary files /dev/null and b/src/lib/libraries/decks/story/sprite-library.gif differ diff --git a/src/lib/libraries/decks/story/story--library.gif b/src/lib/libraries/decks/story/story--library.gif new file mode 100644 index 0000000000000000000000000000000000000000..f29bbdf2de57f35f453c1ded63491f561475e116 Binary files /dev/null and b/src/lib/libraries/decks/story/story--library.gif differ diff --git a/src/lib/libraries/decks/videos/add-backdrop.jpg b/src/lib/libraries/decks/videos/add-backdrop.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a40fed4aba638941d2baa77e7f29a8299f6e5b35 Binary files /dev/null and b/src/lib/libraries/decks/videos/add-backdrop.jpg differ diff --git a/src/lib/libraries/decks/videos/add-effects.jpg b/src/lib/libraries/decks/videos/add-effects.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a6e1a135529beb9a8dc8f583d27a8896f01326ce Binary files /dev/null and b/src/lib/libraries/decks/videos/add-effects.jpg differ diff --git a/src/lib/libraries/decks/videos/change-size.jpg b/src/lib/libraries/decks/videos/change-size.jpg new file mode 100644 index 0000000000000000000000000000000000000000..93958ad158f73f1b7cb754d75e9866f108a6794e Binary files /dev/null and b/src/lib/libraries/decks/videos/change-size.jpg differ diff --git a/src/lib/libraries/decks/videos/glide-around.jpg b/src/lib/libraries/decks/videos/glide-around.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f14d947a2383cca810145ad256871d13b7d5019d Binary files /dev/null and b/src/lib/libraries/decks/videos/glide-around.jpg differ diff --git a/src/lib/libraries/decks/videos/hide-and-show.jpg b/src/lib/libraries/decks/videos/hide-and-show.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6b095b4ea94080b34adb83805e9ea2612a21fe9b Binary files /dev/null and b/src/lib/libraries/decks/videos/hide-and-show.jpg differ diff --git a/src/lib/libraries/decks/videos/move-arrow-keys.jpg b/src/lib/libraries/decks/videos/move-arrow-keys.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2e42e189a48a26646db9a8f96d32a1e0c3ccf47b Binary files /dev/null and b/src/lib/libraries/decks/videos/move-arrow-keys.jpg differ diff --git a/src/lib/libraries/decks/videos/spin.jpg b/src/lib/libraries/decks/videos/spin.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5bbef48845f955eb23d0399bf61f79eec30ef99e Binary files /dev/null and b/src/lib/libraries/decks/videos/spin.jpg differ diff --git a/src/lib/libraries/decks/videos/switch-costume.jpg b/src/lib/libraries/decks/videos/switch-costume.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bfbfa87d5484b68ad9981cb56e891c2e1d5161bf Binary files /dev/null and b/src/lib/libraries/decks/videos/switch-costume.jpg differ diff --git a/src/lib/libraries/decks/zoom/click-turn--zoomed.gif b/src/lib/libraries/decks/zoom/click-turn--zoomed.gif new file mode 100644 index 0000000000000000000000000000000000000000..68cbbd8274fa79ee06e4a521e23d95da730b3250 Binary files /dev/null and b/src/lib/libraries/decks/zoom/click-turn--zoomed.gif differ diff --git a/src/lib/libraries/decks/zoom/click-turn.gif b/src/lib/libraries/decks/zoom/click-turn.gif new file mode 100644 index 0000000000000000000000000000000000000000..8e10e3db9594795418d20f9679c2db1ed8456cb1 Binary files /dev/null and b/src/lib/libraries/decks/zoom/click-turn.gif differ diff --git a/src/lib/libraries/decks/zoom/color--zoomed.gif b/src/lib/libraries/decks/zoom/color--zoomed.gif new file mode 100644 index 0000000000000000000000000000000000000000..30734631014550d87ae78fd45f05675f6e0f5437 Binary files /dev/null and b/src/lib/libraries/decks/zoom/color--zoomed.gif differ diff --git a/src/lib/libraries/decks/zoom/color.gif b/src/lib/libraries/decks/zoom/color.gif new file mode 100644 index 0000000000000000000000000000000000000000..5639976b4c28bc5043b88144afef465be6df2253 Binary files /dev/null and b/src/lib/libraries/decks/zoom/color.gif differ diff --git a/src/lib/libraries/decks/zoom/drag-turn--zoomed.gif b/src/lib/libraries/decks/zoom/drag-turn--zoomed.gif new file mode 100644 index 0000000000000000000000000000000000000000..af50185eeb4597a0c6967a1f24c006154297c8d7 Binary files /dev/null and b/src/lib/libraries/decks/zoom/drag-turn--zoomed.gif differ diff --git a/src/lib/libraries/decks/zoom/drag-turn.gif b/src/lib/libraries/decks/zoom/drag-turn.gif new file mode 100644 index 0000000000000000000000000000000000000000..58d09eff4cd0758fad1201025a6f885d70b456ac Binary files /dev/null and b/src/lib/libraries/decks/zoom/drag-turn.gif differ diff --git a/src/lib/libraries/decks/zoom/edge.gif b/src/lib/libraries/decks/zoom/edge.gif new file mode 100644 index 0000000000000000000000000000000000000000..5069d83a9ab59d78274fef20703ca5128653e900 Binary files /dev/null and b/src/lib/libraries/decks/zoom/edge.gif differ diff --git a/src/lib/libraries/decks/zoom/forever--zoomed.gif b/src/lib/libraries/decks/zoom/forever--zoomed.gif new file mode 100644 index 0000000000000000000000000000000000000000..30d94b36f1688bfbd7cf897ba12ee729c7ec6a35 Binary files /dev/null and b/src/lib/libraries/decks/zoom/forever--zoomed.gif differ diff --git a/src/lib/libraries/decks/zoom/forever.gif b/src/lib/libraries/decks/zoom/forever.gif new file mode 100644 index 0000000000000000000000000000000000000000..013f925a1c484daab40abd0f3ad7ac677edfc63a Binary files /dev/null and b/src/lib/libraries/decks/zoom/forever.gif differ diff --git a/src/lib/libraries/decks/zoom/green-flag.gif b/src/lib/libraries/decks/zoom/green-flag.gif new file mode 100644 index 0000000000000000000000000000000000000000..dadceba6f918a79475701432645251da76859345 Binary files /dev/null and b/src/lib/libraries/decks/zoom/green-flag.gif differ diff --git a/src/lib/libraries/decks/zoom/loudness.gif b/src/lib/libraries/decks/zoom/loudness.gif new file mode 100644 index 0000000000000000000000000000000000000000..11fb68ca8948df097aae30dd9c48dfb47594bc2a Binary files /dev/null and b/src/lib/libraries/decks/zoom/loudness.gif differ diff --git a/src/lib/libraries/decks/zoom/move--zoomed.gif b/src/lib/libraries/decks/zoom/move--zoomed.gif new file mode 100644 index 0000000000000000000000000000000000000000..b3e36a5d9d803ec543d02e5bcc37efc0c2819439 Binary files /dev/null and b/src/lib/libraries/decks/zoom/move--zoomed.gif differ diff --git a/src/lib/libraries/decks/zoom/move.gif b/src/lib/libraries/decks/zoom/move.gif new file mode 100644 index 0000000000000000000000000000000000000000..97b1efe86449626e79495ee48a0cb4ac9edc60cc Binary files /dev/null and b/src/lib/libraries/decks/zoom/move.gif differ diff --git a/src/lib/libraries/decks/zoom/stop.gif b/src/lib/libraries/decks/zoom/stop.gif new file mode 100644 index 0000000000000000000000000000000000000000..cbc2b39a7a90ee21da81cce7f58f07f93acc8fbc Binary files /dev/null and b/src/lib/libraries/decks/zoom/stop.gif differ diff --git a/src/lib/libraries/decks/zoom/zoom-around--library.gif b/src/lib/libraries/decks/zoom/zoom-around--library.gif new file mode 100644 index 0000000000000000000000000000000000000000..a7d87c6cd92c56cbfe6155131d58f7573c764b54 Binary files /dev/null and b/src/lib/libraries/decks/zoom/zoom-around--library.gif differ diff --git a/src/lib/libraries/decks/zoom/zoom-thumb.gif b/src/lib/libraries/decks/zoom/zoom-thumb.gif new file mode 100644 index 0000000000000000000000000000000000000000..df8410a9912e5ad5d5fc65eeb9a7db82e9ec9abe Binary files /dev/null and b/src/lib/libraries/decks/zoom/zoom-thumb.gif differ diff --git a/src/reducers/cards.js b/src/reducers/cards.js new file mode 100644 index 0000000000000000000000000000000000000000..334225639ca579c80c3ab62ee6d267d10b81ef97 --- /dev/null +++ b/src/reducers/cards.js @@ -0,0 +1,118 @@ +import decks from '../lib/libraries/decks/index.jsx'; + +const CLOSE_CARDS = 'scratch-gui/cards/CLOSE_CARDS'; +const VIEW_CARDS = 'scratch-gui/cards/VIEW_CARDS'; +const ACTIVATE_DECK = 'scratch-gui/cards/ACTIVATE_DECK'; +const NEXT_STEP = 'scratch-gui/cards/NEXT_STEP'; +const PREV_STEP = 'scratch-gui/cards/PREV_STEP'; +const DRAG_CARD = 'scratch-gui/cards/DRAG_CARD'; +const START_DRAG = 'scratch-gui/cards/START_DRAG'; +const END_DRAG = 'scratch-gui/cards/END_DRAG'; + +const initialState = { + visible: false, + content: decks, + activeDeckId: null, + step: 0, + x: 292, + y: 365, + dragging: false +}; + +const reducer = function (state, action) { + if (typeof state === 'undefined') state = initialState; + switch (action.type) { + case CLOSE_CARDS: + return Object.assign({}, state, { + visible: false + }); + case VIEW_CARDS: + return Object.assign({}, state, { + visible: true + }); + case ACTIVATE_DECK: + return Object.assign({}, state, { + activeDeckId: action.activeDeckId, + step: 0, + visible: true + }); + case NEXT_STEP: + if (state.activeDeckId !== null) { + return Object.assign({}, state, { + step: state.step + 1 + }); + } + return state; + case PREV_STEP: + if (state.activeDeckId !== null) { + if (state.step > 0) { + return Object.assign({}, state, { + step: state.step - 1 + }); + } + } + return state; + case DRAG_CARD: + return Object.assign({}, state, { + x: action.x, + y: action.y + }); + case START_DRAG: + return Object.assign({}, state, { + dragging: true + }); + case END_DRAG: + return Object.assign({}, state, { + dragging: false + }); + default: + return state; + } +}; + +const activateDeck = function (activeDeckId) { + return { + type: ACTIVATE_DECK, + activeDeckId + }; +}; + +const viewCards = function () { + return {type: VIEW_CARDS}; +}; + +const closeCards = function () { + return {type: CLOSE_CARDS}; +}; + +const nextStep = function () { + return {type: NEXT_STEP}; +}; + +const prevStep = function () { + return {type: PREV_STEP}; +}; + +const dragCard = function (x, y) { + return {type: DRAG_CARD, x, y}; +}; + +const startDrag = function () { + return {type: START_DRAG}; +}; + +const endDrag = function () { + return {type: END_DRAG}; +}; + +export { + reducer as default, + activateDeck, + viewCards, + closeCards, + nextStep, + prevStep, + dragCard, + startDrag, + endDrag +}; diff --git a/src/reducers/gui.js b/src/reducers/gui.js index 64d84634297fb03efefbc5dbc31592d2cdcf65b5..15218e100f83425f791e1f67a2607f7a3ec2253c 100644 --- a/src/reducers/gui.js +++ b/src/reducers/gui.js @@ -1,4 +1,5 @@ import {combineReducers} from 'redux'; +import cardsReducer from './cards'; import colorPickerReducer from './color-picker'; import customProceduresReducer from './custom-procedures'; import blockDragReducer from './block-drag'; @@ -17,6 +18,7 @@ import {ScratchPaintReducer} from 'scratch-paint'; export default combineReducers({ blockDrag: blockDragReducer, + cards: cardsReducer, colorPicker: colorPickerReducer, customProcedures: customProceduresReducer, editorTab: editorTabReducer, diff --git a/src/reducers/modals.js b/src/reducers/modals.js index ce2e91b3365be8b25a136a636ebcb4996de37cd2..6bb28c81bff32909830ad88c17085fef9c299d04 100644 --- a/src/reducers/modals.js +++ b/src/reducers/modals.js @@ -12,6 +12,8 @@ const MODAL_SOUND_LIBRARY = 'soundLibrary'; const MODAL_SPRITE_LIBRARY = 'spriteLibrary'; const MODAL_SOUND_RECORDER = 'soundRecorder'; +const MODAL_TIPS_LIBRARY = 'tipsLibrary'; + const initialState = { [MODAL_BACKDROP_LIBRARY]: false, @@ -21,7 +23,8 @@ const initialState = { [MODAL_PREVIEW_INFO]: true, [MODAL_SOUND_LIBRARY]: false, [MODAL_SPRITE_LIBRARY]: false, - [MODAL_SOUND_RECORDER]: false + [MODAL_SOUND_RECORDER]: false, + [MODAL_TIPS_LIBRARY]: false }; const reducer = function (state, action) { @@ -83,6 +86,10 @@ const openSoundRecorder = function () { analytics.pageview('/modals/microphone'); return openModal(MODAL_SOUND_RECORDER); }; +const openTipsLibrary = function () { + analytics.pageview('/modals/tips'); + return openModal(MODAL_TIPS_LIBRARY); +}; const closeBackdropLibrary = function () { return closeModal(MODAL_BACKDROP_LIBRARY); }; @@ -107,6 +114,9 @@ const closeSoundLibrary = function () { const closeSoundRecorder = function () { return closeModal(MODAL_SOUND_RECORDER); }; +const closeTipsLibrary = function () { + return closeModal(MODAL_TIPS_LIBRARY); +}; export { reducer as default, openBackdropLibrary, @@ -117,6 +127,7 @@ export { openSoundLibrary, openSpriteLibrary, openSoundRecorder, + openTipsLibrary, closeBackdropLibrary, closeCostumeLibrary, closeExtensionLibrary, @@ -124,5 +135,6 @@ export { closePreviewInfo, closeSpriteLibrary, closeSoundLibrary, - closeSoundRecorder + closeSoundRecorder, + closeTipsLibrary }; diff --git a/webpack.config.js b/webpack.config.js index 393e9dbb44ffe9b25971ad3d7195dd319ad6e977..e100c600669b0d91f80b49a4457a13dace5ca1e5 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -90,7 +90,7 @@ module.exports = [ module: { rules: base.module.rules.concat([ { - test: /\.(svg|png|wav)$/, + test: /\.(svg|png|wav|gif|jpg)$/, loader: 'file-loader', options: { outputPath: 'static/assets/' @@ -168,7 +168,8 @@ module.exports = [ module: { rules: base.module.rules.concat([ { - test: /\.(svg|png|wav)$/, + + test: /\.(svg|png|wav|gif|jpg)$/, loader: 'file-loader', options: { outputPath: 'static/assets/',