Merge branch 'media-upload-preview' into 'develop'

Media upload preview

See merge request soapbox-pub/soapbox-fe!508
This commit is contained in:
Alex Gleason 2021-05-17 22:03:55 +00:00
commit 2898f8b129
5 changed files with 46 additions and 10 deletions

View File

@ -99,6 +99,11 @@ class ComposeForm extends ImmutablePureComponent {
return clickableAreaRef ? clickableAreaRef.current : this.form; return clickableAreaRef ? clickableAreaRef.current : this.form;
} }
isEmpty = () => {
const { text, spoilerText, anyMedia } = this.props;
return !(text || spoilerText || anyMedia);
}
isClickOutside = (e) => { isClickOutside = (e) => {
return ![ return ![
// List of elements that shouldn't collapse the composer when clicked // List of elements that shouldn't collapse the composer when clicked
@ -111,7 +116,7 @@ class ComposeForm extends ImmutablePureComponent {
} }
handleClick = (e) => { handleClick = (e) => {
if (this.isClickOutside(e)) { if (this.isEmpty() && this.isClickOutside(e)) {
this.handleClickOutside(); this.handleClickOutside();
} }
} }
@ -238,7 +243,7 @@ class ComposeForm extends ImmutablePureComponent {
render() { render() {
const { intl, onPaste, showSearch, anyMedia, shouldCondense, autoFocus, isModalOpen, maxTootChars } = this.props; const { intl, onPaste, showSearch, anyMedia, shouldCondense, autoFocus, isModalOpen, maxTootChars } = this.props;
const condensed = shouldCondense && !this.props.text && !this.state.composeFocused; const condensed = shouldCondense && !this.state.composeFocused && this.isEmpty() && !this.props.isUploading;
const disabled = this.props.isSubmitting; const disabled = this.props.isSubmitting;
const text = [this.props.spoilerText, countableText(this.props.text)].join(''); const text = [this.props.spoilerText, countableText(this.props.text)].join('');
const disabledButton = disabled || this.props.isUploading || this.props.isChangingUpload || length(text) > maxTootChars || (text.length !== 0 && text.trim().length === 0 && !anyMedia); const disabledButton = disabled || this.props.isUploading || this.props.isChangingUpload || length(text) > maxTootChars || (text.length !== 0 && text.trim().length === 0 && !anyMedia);

View File

@ -27,7 +27,6 @@ class Upload extends ImmutablePureComponent {
onDescriptionChange: PropTypes.func.isRequired, onDescriptionChange: PropTypes.func.isRequired,
onOpenFocalPoint: PropTypes.func.isRequired, onOpenFocalPoint: PropTypes.func.isRequired,
onSubmit: PropTypes.func.isRequired, onSubmit: PropTypes.func.isRequired,
features: PropTypes.object,
}; };
state = { state = {
@ -87,6 +86,10 @@ class Upload extends ImmutablePureComponent {
} }
} }
handleOpenModal = () => {
this.props.onOpenModal(this.props.media);
}
render() { render() {
const { intl, media } = this.props; const { intl, media } = this.props;
const active = this.state.hovered || this.state.focused; const active = this.state.hovered || this.state.focused;
@ -105,12 +108,12 @@ class Upload extends ImmutablePureComponent {
className={classNames('compose-form__upload-thumbnail', `${mediaType}`)} className={classNames('compose-form__upload-thumbnail', `${mediaType}`)}
style={{ style={{
transform: `scale(${scale})`, transform: `scale(${scale})`,
backgroundImage: (mediaType !== 'video' && mediaType !== 'audio' ? `url(${media.get('preview_url')})` : null), backgroundImage: mediaType === 'image' ? `url(${media.get('preview_url')})`: null,
backgroundPosition: `${x}% ${y}%` }} backgroundPosition: `${x}% ${y}%` }}
> >
<div className={classNames('compose-form__upload__actions', { active })}> <div className={classNames('compose-form__upload__actions', { active })}>
<button className='icon-button' onClick={this.handleUndoClick}><Icon id='times' /> <FormattedMessage id='upload_form.undo' defaultMessage='Delete' /></button> <button className='icon-button' onClick={this.handleUndoClick}><Icon id='times' /> <FormattedMessage id='upload_form.undo' defaultMessage='Delete' /></button>
{this.props.features.focalPoint && media.get('type') === 'image' && <button className='icon-button' onClick={this.handleFocalPointClick}><Icon id='crosshairs' /> <FormattedMessage id='upload_form.focus' defaultMessage='Change preview' /></button>} <button className='icon-button' onClick={this.handleOpenModal}><Icon id='search-plus' /> <FormattedMessage id='upload_form.preview' defaultMessage='Preview' /></button>
</div> </div>
<div className={classNames('compose-form__upload-description', { active })}> <div className={classNames('compose-form__upload-description', { active })}>
@ -128,6 +131,14 @@ class Upload extends ImmutablePureComponent {
/> />
</label> </label>
</div> </div>
<div className='compose-form__upload-preview'>
{mediaType === 'video' && (
<video autoPlay playsInline muted loop>
<source src={media.get('preview_url')} />
</video>
)}
</div>
</div> </div>
)} )}
</Motion> </Motion>

View File

@ -3,7 +3,7 @@ import UploadButton from '../components/upload_button';
import { uploadCompose } from '../../../actions/compose'; import { uploadCompose } from '../../../actions/compose';
const mapStateToProps = state => ({ const mapStateToProps = state => ({
disabled: state.getIn(['compose', 'is_uploading']) || (state.getIn(['compose', 'media_attachments']).size > 3 || state.getIn(['compose', 'media_attachments']).some(m => m.get('type') === 'video')), disabled: state.getIn(['compose', 'is_uploading']),
resetFileKey: state.getIn(['compose', 'resetFileKey']), resetFileKey: state.getIn(['compose', 'resetFileKey']),
}); });

View File

@ -3,11 +3,10 @@ import Upload from '../components/upload';
import { undoUploadCompose, changeUploadCompose } from '../../../actions/compose'; import { undoUploadCompose, changeUploadCompose } from '../../../actions/compose';
import { openModal } from '../../../actions/modal'; import { openModal } from '../../../actions/modal';
import { submitCompose } from '../../../actions/compose'; import { submitCompose } from '../../../actions/compose';
import { getFeatures } from 'soapbox/utils/features'; import { List as ImmutableList } from 'immutable';
const mapStateToProps = (state, { id }) => ({ const mapStateToProps = (state, { id }) => ({
media: state.getIn(['compose', 'media_attachments']).find(item => item.get('id') === id), media: state.getIn(['compose', 'media_attachments']).find(item => item.get('id') === id),
features: getFeatures(state.get('instance')),
}); });
const mapDispatchToProps = dispatch => ({ const mapDispatchToProps = dispatch => ({
@ -24,6 +23,10 @@ const mapDispatchToProps = dispatch => ({
dispatch(openModal('FOCAL_POINT', { id })); dispatch(openModal('FOCAL_POINT', { id }));
}, },
onOpenModal: media => {
dispatch(openModal('MEDIA', { media: ImmutableList.of(media), index: 0 }));
},
onSubmit(router) { onSubmit(router) {
dispatch(submitCompose(router)); dispatch(submitCompose(router));
}, },

View File

@ -277,16 +277,33 @@
} }
&.active { opacity: 1; } &.active { opacity: 1; }
} }
&-preview {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: -1;
video {
width: 100%;
height: 100%;
object-fit: cover;
}
}
} }
.compose-form__upload-thumbnail { .compose-form__upload-thumbnail {
border-radius: 4px; border-radius: 4px;
background-position: center; background-position: center;
background-size: contain;
background-repeat: no-repeat; background-repeat: no-repeat;
height: 140px; height: 160px;
width: 100%; width: 100%;
overflow: hidden; overflow: hidden;
position: relative;
&.video { &.video {
background-image: url('../images/video-placeholder.png'); background-image: url('../images/video-placeholder.png');