From bc4fa6b198557a7f3989eb0865e2c77ac7451d29 Mon Sep 17 00:00:00 2001 From: kibigo! Date: Sun, 3 Dec 2017 23:26:40 -0800 Subject: Rename themes -> flavours ? ? --- .../glitch/features/ui/components/doodle_modal.js | 614 --------------------- 1 file changed, 614 deletions(-) delete mode 100644 app/javascript/themes/glitch/features/ui/components/doodle_modal.js (limited to 'app/javascript/themes/glitch/features/ui/components/doodle_modal.js') diff --git a/app/javascript/themes/glitch/features/ui/components/doodle_modal.js b/app/javascript/themes/glitch/features/ui/components/doodle_modal.js deleted file mode 100644 index 819656dbf..000000000 --- a/app/javascript/themes/glitch/features/ui/components/doodle_modal.js +++ /dev/null @@ -1,614 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import Button from 'themes/glitch/components/button'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import Atrament from 'atrament'; // the doodling library -import { connect } from 'react-redux'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import { doodleSet, uploadCompose } from 'themes/glitch/actions/compose'; -import IconButton from 'themes/glitch/components/icon_button'; -import { debounce, mapValues } from 'lodash'; -import classNames from 'classnames'; - -// palette nicked from MyPaint, CC0 -const palette = [ - ['rgb( 0, 0, 0)', 'Black'], - ['rgb( 38, 38, 38)', 'Gray 15'], - ['rgb( 77, 77, 77)', 'Grey 30'], - ['rgb(128, 128, 128)', 'Grey 50'], - ['rgb(171, 171, 171)', 'Grey 67'], - ['rgb(217, 217, 217)', 'Grey 85'], - ['rgb(255, 255, 255)', 'White'], - ['rgb(128, 0, 0)', 'Maroon'], - ['rgb(209, 0, 0)', 'English-red'], - ['rgb(255, 54, 34)', 'Tomato'], - ['rgb(252, 60, 3)', 'Orange-red'], - ['rgb(255, 140, 105)', 'Salmon'], - ['rgb(252, 232, 32)', 'Cadium-yellow'], - ['rgb(243, 253, 37)', 'Lemon yellow'], - ['rgb(121, 5, 35)', 'Dark crimson'], - ['rgb(169, 32, 62)', 'Deep carmine'], - ['rgb(255, 140, 0)', 'Orange'], - ['rgb(255, 168, 18)', 'Dark tangerine'], - ['rgb(217, 144, 88)', 'Persian orange'], - ['rgb(194, 178, 128)', 'Sand'], - ['rgb(255, 229, 180)', 'Peach'], - ['rgb(100, 54, 46)', 'Bole'], - ['rgb(108, 41, 52)', 'Dark cordovan'], - ['rgb(163, 65, 44)', 'Chestnut'], - ['rgb(228, 136, 100)', 'Dark salmon'], - ['rgb(255, 195, 143)', 'Apricot'], - ['rgb(255, 219, 188)', 'Unbleached silk'], - ['rgb(242, 227, 198)', 'Straw'], - ['rgb( 53, 19, 13)', 'Bistre'], - ['rgb( 84, 42, 14)', 'Dark chocolate'], - ['rgb(102, 51, 43)', 'Burnt sienna'], - ['rgb(184, 66, 0)', 'Sienna'], - ['rgb(216, 153, 12)', 'Yellow ochre'], - ['rgb(210, 180, 140)', 'Tan'], - ['rgb(232, 204, 144)', 'Dark wheat'], - ['rgb( 0, 49, 83)', 'Prussian blue'], - ['rgb( 48, 69, 119)', 'Dark grey blue'], - ['rgb( 0, 71, 171)', 'Cobalt blue'], - ['rgb( 31, 117, 254)', 'Blue'], - ['rgb(120, 180, 255)', 'Bright french blue'], - ['rgb(171, 200, 255)', 'Bright steel blue'], - ['rgb(208, 231, 255)', 'Ice blue'], - ['rgb( 30, 51, 58)', 'Medium jungle green'], - ['rgb( 47, 79, 79)', 'Dark slate grey'], - ['rgb( 74, 104, 93)', 'Dark grullo green'], - ['rgb( 0, 128, 128)', 'Teal'], - ['rgb( 67, 170, 176)', 'Turquoise'], - ['rgb(109, 174, 199)', 'Cerulean frost'], - ['rgb(173, 217, 186)', 'Tiffany green'], - ['rgb( 22, 34, 29)', 'Gray-asparagus'], - ['rgb( 36, 48, 45)', 'Medium dark teal'], - ['rgb( 74, 104, 93)', 'Xanadu'], - ['rgb(119, 198, 121)', 'Mint'], - ['rgb(175, 205, 182)', 'Timberwolf'], - ['rgb(185, 245, 246)', 'Celeste'], - ['rgb(193, 255, 234)', 'Aquamarine'], - ['rgb( 29, 52, 35)', 'Cal Poly Pomona'], - ['rgb( 1, 68, 33)', 'Forest green'], - ['rgb( 42, 128, 0)', 'Napier green'], - ['rgb(128, 128, 0)', 'Olive'], - ['rgb( 65, 156, 105)', 'Sea green'], - ['rgb(189, 246, 29)', 'Green-yellow'], - ['rgb(231, 244, 134)', 'Bright chartreuse'], - ['rgb(138, 23, 137)', 'Purple'], - ['rgb( 78, 39, 138)', 'Violet'], - ['rgb(193, 75, 110)', 'Dark thulian pink'], - ['rgb(222, 49, 99)', 'Cerise'], - ['rgb(255, 20, 147)', 'Deep pink'], - ['rgb(255, 102, 204)', 'Rose pink'], - ['rgb(255, 203, 219)', 'Pink'], - ['rgb(255, 255, 255)', 'White'], - ['rgb(229, 17, 1)', 'RGB Red'], - ['rgb( 0, 255, 0)', 'RGB Green'], - ['rgb( 0, 0, 255)', 'RGB Blue'], - ['rgb( 0, 255, 255)', 'CMYK Cyan'], - ['rgb(255, 0, 255)', 'CMYK Magenta'], - ['rgb(255, 255, 0)', 'CMYK Yellow'], -]; - -// re-arrange to the right order for display -let palReordered = []; -for (let row = 0; row < 7; row++) { - for (let col = 0; col < 11; col++) { - palReordered.push(palette[col * 7 + row]); - } - palReordered.push(null); // null indicates a
-} - -// Utility for converting base64 image to binary for upload -// https://stackoverflow.com/questions/35940290/how-to-convert-base64-string-to-javascript-file-object-like-as-from-file-input-f -function dataURLtoFile(dataurl, filename) { - let arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], - bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); - while(n--){ - u8arr[n] = bstr.charCodeAt(n); - } - return new File([u8arr], filename, { type: mime }); -} - -const DOODLE_SIZES = { - normal: [500, 500, 'Square 500'], - tootbanner: [702, 330, 'Tootbanner'], - s640x480: [640, 480, '640×480 - 480p'], - s800x600: [800, 600, '800×600 - SVGA'], - s720x480: [720, 405, '720x405 - 16:9'], -}; - - -const mapStateToProps = state => ({ - options: state.getIn(['compose', 'doodle']), -}); - -const mapDispatchToProps = dispatch => ({ - /** Set options in the redux store */ - setOpt: (opts) => dispatch(doodleSet(opts)), - /** Submit doodle for upload */ - submit: (file) => dispatch(uploadCompose([file])), -}); - -/** - * Doodling dialog with drawing canvas - * - * Keyboard shortcuts: - * - Delete: Clear screen, fill with background color - * - Backspace, Ctrl+Z: Undo one step - * - Ctrl held while drawing: Use background color - * - Shift held while clicking screen: Use fill tool - * - * Palette: - * - Left mouse button: pick foreground - * - Ctrl + left mouse button: pick background - * - Right mouse button: pick background - */ -@connect(mapStateToProps, mapDispatchToProps) -export default class DoodleModal extends ImmutablePureComponent { - - static propTypes = { - options: ImmutablePropTypes.map, - onClose: PropTypes.func.isRequired, - setOpt: PropTypes.func.isRequired, - submit: PropTypes.func.isRequired, - }; - - //region Option getters/setters - - /** Foreground color */ - get fg () { - return this.props.options.get('fg'); - } - set fg (value) { - this.props.setOpt({ fg: value }); - } - - /** Background color */ - get bg () { - return this.props.options.get('bg'); - } - set bg (value) { - this.props.setOpt({ bg: value }); - } - - /** Swap Fg and Bg for drawing */ - get swapped () { - return this.props.options.get('swapped'); - } - set swapped (value) { - this.props.setOpt({ swapped: value }); - } - - /** Mode - 'draw' or 'fill' */ - get mode () { - return this.props.options.get('mode'); - } - set mode (value) { - this.props.setOpt({ mode: value }); - } - - /** Base line weight */ - get weight () { - return this.props.options.get('weight'); - } - set weight (value) { - this.props.setOpt({ weight: value }); - } - - /** Drawing opacity */ - get opacity () { - return this.props.options.get('opacity'); - } - set opacity (value) { - this.props.setOpt({ opacity: value }); - } - - /** Adaptive stroke - change width with speed */ - get adaptiveStroke () { - return this.props.options.get('adaptiveStroke'); - } - set adaptiveStroke (value) { - this.props.setOpt({ adaptiveStroke: value }); - } - - /** Smoothing (for mouse drawing) */ - get smoothing () { - return this.props.options.get('smoothing'); - } - set smoothing (value) { - this.props.setOpt({ smoothing: value }); - } - - /** Size preset */ - get size () { - return this.props.options.get('size'); - } - set size (value) { - this.props.setOpt({ size: value }); - } - - //endregion - - /** Key up handler */ - handleKeyUp = (e) => { - if (e.target.nodeName === 'INPUT') return; - - if (e.key === 'Delete') { - e.preventDefault(); - this.handleClearBtn(); - return; - } - - if (e.key === 'Backspace' || (e.key === 'z' && (e.ctrlKey || e.metaKey))) { - e.preventDefault(); - this.undo(); - } - - if (e.key === 'Control' || e.key === 'Meta') { - this.controlHeld = false; - this.swapped = false; - } - - if (e.key === 'Shift') { - this.shiftHeld = false; - this.mode = 'draw'; - } - }; - - /** Key down handler */ - handleKeyDown = (e) => { - if (e.key === 'Control' || e.key === 'Meta') { - this.controlHeld = true; - this.swapped = true; - } - - if (e.key === 'Shift') { - this.shiftHeld = true; - this.mode = 'fill'; - } - }; - - /** - * Component installed in the DOM, do some initial set-up - */ - componentDidMount () { - this.controlHeld = false; - this.shiftHeld = false; - this.swapped = false; - window.addEventListener('keyup', this.handleKeyUp, false); - window.addEventListener('keydown', this.handleKeyDown, false); - }; - - /** - * Tear component down - */ - componentWillUnmount () { - window.removeEventListener('keyup', this.handleKeyUp, false); - window.removeEventListener('keydown', this.handleKeyDown, false); - if (this.sketcher) this.sketcher.destroy(); - } - - /** - * Set reference to the canvas element. - * This is called during component init - * - * @param elem - canvas element - */ - setCanvasRef = (elem) => { - this.canvas = elem; - if (elem) { - elem.addEventListener('dirty', () => { - this.saveUndo(); - this.sketcher._dirty = false; - }); - - elem.addEventListener('click', () => { - // sketcher bug - does not fire dirty on fill - if (this.mode === 'fill') { - this.saveUndo(); - } - }); - - // prevent context menu - elem.addEventListener('contextmenu', (e) => { - e.preventDefault(); - }); - - elem.addEventListener('mousedown', (e) => { - if (e.button === 2) { - this.swapped = true; - } - }); - - elem.addEventListener('mouseup', (e) => { - if (e.button === 2) { - this.swapped = this.controlHeld; - } - }); - - this.initSketcher(elem); - this.mode = 'draw'; // Reset mode - it's confusing if left at 'fill' - } - }; - - /** - * Set up the sketcher instance - * - * @param canvas - canvas element. Null if we're just resizing - */ - initSketcher (canvas = null) { - const sizepreset = DOODLE_SIZES[this.size]; - - if (this.sketcher) this.sketcher.destroy(); - this.sketcher = new Atrament(canvas || this.canvas, sizepreset[0], sizepreset[1]); - - if (canvas) { - this.ctx = this.sketcher.context; - this.updateSketcherSettings(); - } - - this.clearScreen(); - } - - /** - * Done button handler - */ - onDoneButton = () => { - const dataUrl = this.sketcher.toImage(); - const file = dataURLtoFile(dataUrl, 'doodle.png'); - this.props.submit(file); - this.props.onClose(); // close dialog - }; - - /** - * Cancel button handler - */ - onCancelButton = () => { - if (this.undos.length > 1 && !confirm('Discard doodle? All changes will be lost!')) { - return; - } - - this.props.onClose(); // close dialog - }; - - /** - * Update sketcher options based on state - */ - updateSketcherSettings () { - if (!this.sketcher) return; - - if (this.oldSize !== this.size) this.initSketcher(); - - this.sketcher.color = (this.swapped ? this.bg : this.fg); - this.sketcher.opacity = this.opacity; - this.sketcher.weight = this.weight; - this.sketcher.mode = this.mode; - this.sketcher.smoothing = this.smoothing; - this.sketcher.adaptiveStroke = this.adaptiveStroke; - - this.oldSize = this.size; - } - - /** - * Fill screen with background color - */ - clearScreen = () => { - this.ctx.fillStyle = this.bg; - this.ctx.fillRect(-1, -1, this.canvas.width+2, this.canvas.height+2); - this.undos = []; - - this.doSaveUndo(); - }; - - /** - * Undo one step - */ - undo = () => { - if (this.undos.length > 1) { - this.undos.pop(); - const buf = this.undos.pop(); - - this.sketcher.clear(); - this.ctx.putImageData(buf, 0, 0); - this.doSaveUndo(); - } - }; - - /** - * Save canvas content into the undo buffer immediately - */ - doSaveUndo = () => { - this.undos.push(this.ctx.getImageData(0, 0, this.canvas.width, this.canvas.height)); - }; - - /** - * Called on each canvas change. - * Saves canvas content to the undo buffer after some period of inactivity. - */ - saveUndo = debounce(() => { - this.doSaveUndo(); - }, 100); - - /** - * Palette left click. - * Selects Fg color (or Bg, if Control/Meta is held) - * - * @param e - event - */ - onPaletteClick = (e) => { - const c = e.target.dataset.color; - - if (this.controlHeld) { - this.bg = c; - } else { - this.fg = c; - } - - e.target.blur(); - e.preventDefault(); - }; - - /** - * Palette right click. - * Selects Bg color - * - * @param e - event - */ - onPaletteRClick = (e) => { - this.bg = e.target.dataset.color; - e.target.blur(); - e.preventDefault(); - }; - - /** - * Handle click on the Draw mode button - * - * @param e - event - */ - setModeDraw = (e) => { - this.mode = 'draw'; - e.target.blur(); - }; - - /** - * Handle click on the Fill mode button - * - * @param e - event - */ - setModeFill = (e) => { - this.mode = 'fill'; - e.target.blur(); - }; - - /** - * Handle click on Smooth checkbox - * - * @param e - event - */ - tglSmooth = (e) => { - this.smoothing = !this.smoothing; - e.target.blur(); - }; - - /** - * Handle click on Adaptive checkbox - * - * @param e - event - */ - tglAdaptive = (e) => { - this.adaptiveStroke = !this.adaptiveStroke; - e.target.blur(); - }; - - /** - * Handle change of the Weight input field - * - * @param e - event - */ - setWeight = (e) => { - this.weight = +e.target.value || 1; - }; - - /** - * Set size - clalback from the select box - * - * @param e - event - */ - changeSize = (e) => { - let newSize = e.target.value; - if (newSize === this.oldSize) return; - - if (this.undos.length > 1 && !confirm('Change size? This will erase your drawing!')) { - return; - } - - this.size = newSize; - }; - - handleClearBtn = () => { - if (this.undos.length > 1 && !confirm('Clear screen? This will erase your drawing!')) { - return; - } - - this.clearScreen(); - }; - - /** - * Render the component - */ - render () { - this.updateSketcherSettings(); - - return ( -
-
- -
- -
-
-
-
-
-
- - - - -
-
- - - - -
-
- - - - -
-
- -
-
-
- - - - -
-
- { - palReordered.map((c, i) => - c === null ? -
: -
-
-
- ); - } - -} -- cgit