-
+
- {media.get('type') === 'image' && }
-
-
-
-
+
)}
diff --git a/app/javascript/flavours/glitch/features/compose/containers/upload_container.js b/app/javascript/flavours/glitch/features/compose/containers/upload_container.js
index d6bff63ac6..f687fae99d 100644
--- a/app/javascript/flavours/glitch/features/compose/containers/upload_container.js
+++ b/app/javascript/flavours/glitch/features/compose/containers/upload_container.js
@@ -1,6 +1,6 @@
import { connect } from 'react-redux';
import Upload from '../components/upload';
-import { undoUploadCompose, changeUploadCompose } from 'flavours/glitch/actions/compose';
+import { undoUploadCompose } from 'flavours/glitch/actions/compose';
import { openModal } from 'flavours/glitch/actions/modal';
import { submitCompose } from 'flavours/glitch/actions/compose';
@@ -14,10 +14,6 @@ const mapDispatchToProps = dispatch => ({
dispatch(undoUploadCompose(id));
},
- onDescriptionChange: (id, description) => {
- dispatch(changeUploadCompose(id, { description }));
- },
-
onOpenFocalPoint: id => {
dispatch(openModal('FOCAL_POINT', { id }));
},
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
index 57c92cc66f..de87ba83fd 100644
--- a/app/javascript/flavours/glitch/features/ui/components/focal_point_modal.js
+++ b/app/javascript/flavours/glitch/features/ui/components/focal_point_modal.js
@@ -1,11 +1,21 @@
import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
+import PropTypes from 'prop-types';
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';
+import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
+import IconButton from 'flavours/glitch/components/icon_button';
+import Button from 'flavours/glitch/components/button';
+import Video from 'flavours/glitch/features/video';
+
+const messages = defineMessages({
+ close: { id: 'lightbox.close', defaultMessage: 'Close' },
+ apply: { id: 'upload_modal.apply', defaultMessage: 'Apply' },
+ placeholder: { id: 'upload_modal.description_placeholder', defaultMessage: 'A quick brown fox jumps over the lazy dog' },
+});
const mapStateToProps = (state, { id }) => ({
media: state.getIn(['compose', 'media_attachments']).find(item => item.get('id') === id),
@@ -13,17 +23,20 @@ const mapStateToProps = (state, { id }) => ({
const mapDispatchToProps = (dispatch, { id }) => ({
- onSave: (x, y) => {
- dispatch(changeUploadCompose(id, { focus: `${x.toFixed(2)},${y.toFixed(2)}` }));
+ onSave: (description, x, y) => {
+ dispatch(changeUploadCompose(id, { description, focus: `${x.toFixed(2)},${y.toFixed(2)}` }));
},
});
-@connect(mapStateToProps, mapDispatchToProps)
-export default class FocalPointModal extends ImmutablePureComponent {
+export default @connect(mapStateToProps, mapDispatchToProps)
+@injectIntl
+class FocalPointModal extends ImmutablePureComponent {
static propTypes = {
media: ImmutablePropTypes.map.isRequired,
+ onClose: PropTypes.func.isRequired,
+ intl: PropTypes.object.isRequired,
};
state = {
@@ -32,6 +45,8 @@ export default class FocalPointModal extends ImmutablePureComponent {
focusX: 0,
focusY: 0,
dragging: false,
+ description: '',
+ dirty: false,
};
componentWillMount () {
@@ -66,7 +81,6 @@ export default class FocalPointModal extends ImmutablePureComponent {
document.removeEventListener('mouseup', this.handleMouseUp);
this.setState({ dragging: false });
- this.props.onSave(this.state.focusX, this.state.focusY);
}
updatePosition = e => {
@@ -74,46 +88,113 @@ export default class FocalPointModal extends ImmutablePureComponent {
const focusX = (x - .5) * 2;
const focusY = (y - .5) * -2;
- this.setState({ x, y, focusX, focusY });
+ this.setState({ x, y, focusX, focusY, dirty: true });
}
updatePositionFromMedia = media => {
- const focusX = media.getIn(['meta', 'focus', 'x']);
- const focusY = media.getIn(['meta', 'focus', 'y']);
+ const focusX = media.getIn(['meta', 'focus', 'x']);
+ const focusY = media.getIn(['meta', 'focus', 'y']);
+ const description = media.get('description') || '';
if (focusX && focusY) {
const x = (focusX / 2) + .5;
const y = (focusY / -2) + .5;
- this.setState({ x, y, focusX, focusY });
+ this.setState({
+ x,
+ y,
+ focusX,
+ focusY,
+ description,
+ dirty: false,
+ });
} else {
- this.setState({ x: 0.5, y: 0.5, focusX: 0, focusY: 0 });
+ this.setState({
+ x: 0.5,
+ y: 0.5,
+ focusX: 0,
+ focusY: 0,
+ description,
+ dirty: false,
+ });
}
}
+ handleChange = e => {
+ this.setState({ description: e.target.value, dirty: true });
+ }
+
+ handleSubmit = () => {
+ this.props.onSave(this.state.description, this.state.focusX, this.state.focusY);
+ this.props.onClose();
+ }
+
setRef = c => {
this.node = c;
}
render () {
- const { media } = this.props;
- const { x, y, dragging } = this.state;
+ const { media, intl, onClose } = this.props;
+ const { x, y, dragging, description, dirty } = this.state;
const width = media.getIn(['meta', 'original', 'width']) || null;
const height = media.getIn(['meta', 'original', 'height']) || null;
+ const focals = ['image', 'gifv'].includes(media.get('type'));
+
+ const previewRatio = 16/9;
+ const previewWidth = 200;
+ const previewHeight = previewWidth / previewRatio;
return (
-
-
-
+
+
+
+
+
-
-
+
+
+ {focals &&
}
+
+
+
+
+
+
+
+
+
+ {focals && (
+
+ {media.get('type') === 'image' &&
}
+ {media.get('type') === 'gifv' &&
}
+
+
+
+
+
+
+ )}
+
+ {['audio', 'video'].includes(media.get('type')) && (
+
+ )}
+
);
diff --git a/app/javascript/flavours/glitch/features/video/index.js b/app/javascript/flavours/glitch/features/video/index.js
index 112f9d1013..6d51625198 100644
--- a/app/javascript/flavours/glitch/features/video/index.js
+++ b/app/javascript/flavours/glitch/features/video/index.js
@@ -101,6 +101,7 @@ export default class Video extends React.PureComponent {
fullwidth: PropTypes.bool,
detailed: PropTypes.bool,
inline: PropTypes.bool,
+ editable: PropTypes.bool,
cacheWidth: PropTypes.func,
intl: PropTypes.object.isRequired,
visible: PropTypes.bool,
@@ -393,7 +394,7 @@ export default class Video extends React.PureComponent {
}
render () {
- const { preview, src, inline, startTime, onOpenVideo, onCloseVideo, intl, alt, letterbox, fullwidth, detailed, sensitive, link } = this.props;
+ const { preview, src, inline, startTime, onOpenVideo, onCloseVideo, intl, alt, letterbox, fullwidth, detailed, sensitive, link, editable } = this.props;
const { containerWidth, currentTime, duration, volume, buffer, dragging, paused, fullscreen, hovered, muted, revealed } = this.state;
const progress = (currentTime / duration) * 100;
const playerStyle = {};
@@ -401,7 +402,7 @@ export default class Video extends React.PureComponent {
const volumeWidth = (muted) ? 0 : volume * this.volWidth;
const volumeHandleLoc = (muted) ? this.volHandleOffset(0) : this.volHandleOffset(volume);
- const computedClass = classNames('video-player', { inactive: !revealed, detailed, inline: inline && !fullscreen, fullscreen, letterbox, 'full-width': fullwidth });
+ const computedClass = classNames('video-player', { inactive: !revealed, detailed, inline: inline && !fullscreen, fullscreen, editable, letterbox, 'full-width': fullwidth });
let { width, height } = this.props;
@@ -443,7 +444,7 @@ export default class Video extends React.PureComponent {
>
- {revealed &&
}
-
+
@@ -508,7 +509,7 @@ export default class Video extends React.PureComponent {
- {!onCloseVideo && }
+ {(!onCloseVideo && !editable) && }
{(!fullscreen && onOpenVideo) && }
{onCloseVideo && }
diff --git a/app/javascript/flavours/glitch/styles/components/media.scss b/app/javascript/flavours/glitch/styles/components/media.scss
index 8b5d0486db..39ffcae9d0 100644
--- a/app/javascript/flavours/glitch/styles/components/media.scss
+++ b/app/javascript/flavours/glitch/styles/components/media.scss
@@ -338,6 +338,11 @@
position: relative;
background: $base-shadow-color;
max-width: 100%;
+ border-radius: 4px;
+
+ &.editable {
+ border-radius: 0;
+ }
&:focus {
outline: 0;
diff --git a/app/javascript/flavours/glitch/styles/components/modal.scss b/app/javascript/flavours/glitch/styles/components/modal.scss
index a98efee9f4..df4a22329a 100644
--- a/app/javascript/flavours/glitch/styles/components/modal.scss
+++ b/app/javascript/flavours/glitch/styles/components/modal.scss
@@ -577,6 +577,14 @@
}
}
+ .setting-text-label {
+ display: block;
+ color: $inverted-text-color;
+ font-size: 14px;
+ font-weight: 500;
+ margin-bottom: 10px;
+ }
+
.setting-toggle {
margin-top: 20px;
margin-bottom: 24px;
@@ -787,19 +795,18 @@
.focal-point {
position: relative;
- cursor: pointer;
+ cursor: move;
overflow: hidden;
- &.dragging {
- cursor: move;
- }
-
- img {
- max-width: 80vw;
+ img,
+ video {
+ display: block;
max-height: 80vh;
- width: auto;
+ width: 100%;
height: auto;
- margin: auto;
+ margin: 0;
+ object-fit: contain;
+ background: $base-shadow-color;
}
&__reticle {
@@ -819,6 +826,27 @@
top: 0;
left: 0;
}
+
+ &__preview {
+ position: absolute;
+ bottom: 10px;
+ right: 10px;
+ z-index: 2;
+ cursor: default;
+
+ strong {
+ color: $primary-text-color;
+ font-size: 14px;
+ font-weight: 500;
+ display: block;
+ margin-bottom: 5px;
+ }
+
+ div {
+ border-radius: 4px;
+ box-shadow: 0 0 14px rgba($base-shadow-color, 0.2);
+ }
+ }
}
.filtered-status-info {