diff --git a/app/javascript/flavours/glitch/actions/compose.js b/app/javascript/flavours/glitch/actions/compose.js
index b7f706a833..f6c8086fe1 100644
--- a/app/javascript/flavours/glitch/actions/compose.js
+++ b/app/javascript/flavours/glitch/actions/compose.js
@@ -211,11 +211,11 @@ export function uploadCompose(files) {
};
};
-export function changeUploadCompose(id, description) {
+export function changeUploadCompose(id, params) {
return (dispatch, getState) => {
dispatch(changeUploadComposeRequest());
- api(getState).put(`/api/v1/media/${id}`, { description }).then(response => {
+ api(getState).put(`/api/v1/media/${id}`, params).then(response => {
dispatch(changeUploadComposeSuccess(response.data));
}).catch(error => {
dispatch(changeUploadComposeFail(id, error));
diff --git a/app/javascript/flavours/glitch/features/composer/index.js b/app/javascript/flavours/glitch/features/composer/index.js
index 771c5d0e3e..e77d429bed 100644
--- a/app/javascript/flavours/glitch/features/composer/index.js
+++ b/app/javascript/flavours/glitch/features/composer/index.js
@@ -103,7 +103,7 @@ const mapDispatchToProps = (dispatch) => ({
dispatch(changeComposeAdvancedOption(option, value));
},
onChangeDescription(id, description) {
- dispatch(changeUploadCompose(id, description));
+ dispatch(changeUploadCompose(id, { description }));
},
onChangeSensitivity() {
dispatch(changeComposeSensitivity());
@@ -141,6 +141,9 @@ const mapDispatchToProps = (dispatch) => ({
onOpenDoodleModal() {
dispatch(openModal('DOODLE', { noEsc: true }));
},
+ onOpenFocalPointModal(id) {
+ dispatch(openModal('FOCAL_POINT', { id }));
+ },
onSelectSuggestion(position, token, suggestion) {
dispatch(selectComposeSuggestion(position, token, suggestion));
},
@@ -339,6 +342,7 @@ class Composer extends React.Component {
onFetchSuggestions,
onOpenActionsModal,
onOpenDoodleModal,
+ onOpenFocalPointModal,
onUndoUpload,
onUpload,
privacy,
@@ -397,6 +401,7 @@ class Composer extends React.Component {
intl={intl}
media={media}
onChangeDescription={onChangeDescription}
+ onOpenFocalPointModal={onOpenFocalPointModal}
onRemove={onUndoUpload}
progress={progress}
uploading={isUploading}
diff --git a/app/javascript/flavours/glitch/features/composer/upload_form/index.js b/app/javascript/flavours/glitch/features/composer/upload_form/index.js
index 53b14acc71..f3cadc2f58 100644
--- a/app/javascript/flavours/glitch/features/composer/upload_form/index.js
+++ b/app/javascript/flavours/glitch/features/composer/upload_form/index.js
@@ -13,6 +13,7 @@ export default function ComposerUploadForm ({
intl,
media,
onChangeDescription,
+ onOpenFocalPointModal,
onRemove,
progress,
uploading,
@@ -31,8 +32,12 @@ export default function ComposerUploadForm ({
key={item.get('id')}
id={item.get('id')}
intl={intl}
+ focusX={item.getIn(['meta', 'focus', 'x'])}
+ focusY={item.getIn(['meta', 'focus', 'y'])}
+ mediaType={item.get('type')}
preview={item.get('preview_url')}
onChangeDescription={onChangeDescription}
+ onOpenFocalPointModal={onOpenFocalPointModal}
onRemove={onRemove}
/>
))}
@@ -46,8 +51,8 @@ export default function ComposerUploadForm ({
ComposerUploadForm.propTypes = {
intl: PropTypes.object.isRequired,
media: ImmutablePropTypes.list,
- onChangeDescription: PropTypes.func,
- onRemove: PropTypes.func,
+ onChangeDescription: PropTypes.func.isRequired,
+ onRemove: PropTypes.func.isRequired,
progress: PropTypes.number,
uploading: PropTypes.bool,
};
diff --git a/app/javascript/flavours/glitch/features/composer/upload_form/item/index.js b/app/javascript/flavours/glitch/features/composer/upload_form/item/index.js
index ec67b8ef80..b9986588f6 100644
--- a/app/javascript/flavours/glitch/features/composer/upload_form/item/index.js
+++ b/app/javascript/flavours/glitch/features/composer/upload_form/item/index.js
@@ -25,6 +25,10 @@ const messages = defineMessages({
defaultMessage: 'Describe for the visually impaired',
id: 'upload_form.description',
},
+ crop: {
+ defaultMessage: 'Crop',
+ id: 'upload_form.focus',
+ },
});
// Handlers.
@@ -77,6 +81,17 @@ const handlers = {
onRemove(id);
}
},
+
+ // Opens the focal point modal.
+ handleFocalPointClick () {
+ const {
+ id,
+ onOpenFocalPointModal,
+ } = this.props;
+ if (id && onOpenFocalPointModal) {
+ onOpenFocalPointModal(id);
+ }
+ },
};
// The component.
@@ -102,11 +117,15 @@ export default class ComposerUploadFormItem extends React.PureComponent {
handleMouseEnter,
handleMouseLeave,
handleRemove,
+ handleFocalPointClick,
} = this.handlers;
const {
description,
intl,
preview,
+ focusX,
+ focusY,
+ mediaType,
} = this.props;
const {
focused,
@@ -114,6 +133,8 @@ export default class ComposerUploadFormItem extends React.PureComponent {
dirtyDescription,
} = this.state;
const computedClass = classNames('composer--upload_form--item', { active: hovered || focused });
+ const x = ((focusX / 2) + .5) * 100;
+ const y = ((focusY / -2) + .5) * 100;
// The result.
return (
@@ -136,15 +157,15 @@ export default class ComposerUploadFormItem extends React.PureComponent {
style={{
transform: `scale(${scale})`,
backgroundImage: preview ? `url(${preview})` : null,
+ backgroundPosition: `${x}% ${y}%`
}}
>
-