From 534439e73b95814b0db927052c9522c60fc306c5 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Sat, 18 Aug 2018 11:01:53 +0200 Subject: Add focal points support in the composer --- .../features/ui/components/focal_point_modal.js | 122 +++++++++++++++++++++ .../glitch/features/ui/components/modal_root.js | 2 + 2 files changed, 124 insertions(+) create mode 100644 app/javascript/flavours/glitch/features/ui/components/focal_point_modal.js (limited to 'app/javascript/flavours/glitch/features/ui/components') diff --git a/app/javascript/flavours/glitch/features/ui/components/focal_point_modal.js b/app/javascript/flavours/glitch/features/ui/components/focal_point_modal.js new file mode 100644 index 000000000..57c92cc66 --- /dev/null +++ b/app/javascript/flavours/glitch/features/ui/components/focal_point_modal.js @@ -0,0 +1,122 @@ +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { connect } from 'react-redux'; +import ImageLoader from './image_loader'; +import classNames from 'classnames'; +import { changeUploadCompose } from 'flavours/glitch/actions/compose'; +import { getPointerPosition } from 'flavours/glitch/features/video'; + +const mapStateToProps = (state, { id }) => ({ + media: state.getIn(['compose', 'media_attachments']).find(item => item.get('id') === id), +}); + +const mapDispatchToProps = (dispatch, { id }) => ({ + + onSave: (x, y) => { + dispatch(changeUploadCompose(id, { focus: `${x.toFixed(2)},${y.toFixed(2)}` })); + }, + +}); + +@connect(mapStateToProps, mapDispatchToProps) +export default class FocalPointModal extends ImmutablePureComponent { + + static propTypes = { + media: ImmutablePropTypes.map.isRequired, + }; + + state = { + x: 0, + y: 0, + focusX: 0, + focusY: 0, + dragging: false, + }; + + componentWillMount () { + this.updatePositionFromMedia(this.props.media); + } + + componentWillReceiveProps (nextProps) { + if (this.props.media.get('id') !== nextProps.media.get('id')) { + this.updatePositionFromMedia(nextProps.media); + } + } + + componentWillUnmount () { + document.removeEventListener('mousemove', this.handleMouseMove); + document.removeEventListener('mouseup', this.handleMouseUp); + } + + handleMouseDown = e => { + document.addEventListener('mousemove', this.handleMouseMove); + document.addEventListener('mouseup', this.handleMouseUp); + + this.updatePosition(e); + this.setState({ dragging: true }); + } + + handleMouseMove = e => { + this.updatePosition(e); + } + + handleMouseUp = () => { + document.removeEventListener('mousemove', this.handleMouseMove); + document.removeEventListener('mouseup', this.handleMouseUp); + + this.setState({ dragging: false }); + this.props.onSave(this.state.focusX, this.state.focusY); + } + + updatePosition = e => { + const { x, y } = getPointerPosition(this.node, e); + const focusX = (x - .5) * 2; + const focusY = (y - .5) * -2; + + this.setState({ x, y, focusX, focusY }); + } + + updatePositionFromMedia = media => { + const focusX = media.getIn(['meta', 'focus', 'x']); + const focusY = media.getIn(['meta', 'focus', 'y']); + + if (focusX && focusY) { + const x = (focusX / 2) + .5; + const y = (focusY / -2) + .5; + + this.setState({ x, y, focusX, focusY }); + } else { + this.setState({ x: 0.5, y: 0.5, focusX: 0, focusY: 0 }); + } + } + + setRef = c => { + this.node = c; + } + + render () { + const { media } = this.props; + const { x, y, dragging } = this.state; + + const width = media.getIn(['meta', 'original', 'width']) || null; + const height = media.getIn(['meta', 'original', 'height']) || null; + + return ( +
+
+ + +
+
+
+
+ ); + } + +} diff --git a/app/javascript/flavours/glitch/features/ui/components/modal_root.js b/app/javascript/flavours/glitch/features/ui/components/modal_root.js index e54ab9a52..23a7603d8 100644 --- a/app/javascript/flavours/glitch/features/ui/components/modal_root.js +++ b/app/javascript/flavours/glitch/features/ui/components/modal_root.js @@ -11,6 +11,7 @@ import BoostModal from './boost_modal'; import FavouriteModal from './favourite_modal'; import DoodleModal from './doodle_modal'; import ConfirmationModal from './confirmation_modal'; +import FocalPointModal from './focal_point_modal'; import { OnboardingModal, MuteModal, @@ -34,6 +35,7 @@ const MODAL_COMPONENTS = { 'ACTIONS': () => Promise.resolve({ default: ActionsModal }), 'EMBED': EmbedModal, 'LIST_EDITOR': ListEditor, + 'FOCAL_POINT': () => Promise.resolve({ default: FocalPointModal }), }; export default class ModalRoot extends React.PureComponent { -- cgit