diff --git a/app/javascript/flavours/glitch/components/extended_video_player.js b/app/javascript/flavours/glitch/components/extended_video_player.js
index f8bd067e8e..9e2f6835a8 100644
--- a/app/javascript/flavours/glitch/components/extended_video_player.js
+++ b/app/javascript/flavours/glitch/components/extended_video_player.js
@@ -11,6 +11,7 @@ export default class ExtendedVideoPlayer extends React.PureComponent {
time: PropTypes.number,
controls: PropTypes.bool.isRequired,
muted: PropTypes.bool.isRequired,
+ onClick: PropTypes.func,
};
handleLoadedData = () => {
@@ -31,6 +32,12 @@ export default class ExtendedVideoPlayer extends React.PureComponent {
this.video = c;
}
+ handleClick = e => {
+ e.stopPropagation();
+ const handler = this.props.onClick;
+ if (handler) handler();
+ }
+
render () {
const { src, muted, controls, alt } = this.props;
@@ -46,6 +53,7 @@ export default class ExtendedVideoPlayer extends React.PureComponent {
muted={muted}
controls={controls}
loop={!controls}
+ onClick={this.handleClick}
/>
);
diff --git a/app/javascript/flavours/glitch/features/status/components/card.js b/app/javascript/flavours/glitch/features/status/components/card.js
index bb83374b9b..680bf63ab7 100644
--- a/app/javascript/flavours/glitch/features/status/components/card.js
+++ b/app/javascript/flavours/glitch/features/status/components/card.js
@@ -1,5 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
+import Immutable from 'immutable';
import ImmutablePropTypes from 'react-immutable-proptypes';
import punycode from 'punycode';
import classnames from 'classnames';
@@ -24,6 +25,7 @@ export default class Card extends React.PureComponent {
static propTypes = {
card: ImmutablePropTypes.map,
maxDescription: PropTypes.number,
+ onOpenMedia: PropTypes.func.isRequired,
};
static defaultProps = {
@@ -34,6 +36,27 @@ export default class Card extends React.PureComponent {
width: 0,
};
+ handlePhotoClick = () => {
+ const { card, onOpenMedia } = this.props;
+
+ onOpenMedia(
+ Immutable.fromJS([
+ {
+ type: 'image',
+ url: card.get('url'),
+ description: card.get('title'),
+ meta: {
+ original: {
+ width: card.get('width'),
+ height: card.get('height'),
+ },
+ },
+ },
+ ]),
+ 0
+ );
+ };
+
renderLink () {
const { card, maxDescription } = this.props;
@@ -73,9 +96,16 @@ export default class Card extends React.PureComponent {
const { card } = this.props;
return (
-
-
-
+
);
}
diff --git a/app/javascript/flavours/glitch/features/status/components/detailed_status.js b/app/javascript/flavours/glitch/features/status/components/detailed_status.js
index 9e42481c5a..684cd797bb 100644
--- a/app/javascript/flavours/glitch/features/status/components/detailed_status.js
+++ b/app/javascript/flavours/glitch/features/status/components/detailed_status.js
@@ -77,7 +77,7 @@ export default class DetailedStatus extends ImmutablePureComponent {
);
mediaIcon = 'picture-o';
}
- } else media = ;
+ } else media = ;
if (status.get('application')) {
applicationLink = ยท {status.getIn(['application', 'name'])};
diff --git a/app/javascript/flavours/glitch/features/ui/components/image_loader.js b/app/javascript/flavours/glitch/features/ui/components/image_loader.js
index aad594380e..c7360a7264 100644
--- a/app/javascript/flavours/glitch/features/ui/components/image_loader.js
+++ b/app/javascript/flavours/glitch/features/ui/components/image_loader.js
@@ -1,15 +1,17 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
+import ZoomableImage from './zoomable_image';
export default class ImageLoader extends React.PureComponent {
static propTypes = {
alt: PropTypes.string,
src: PropTypes.string.isRequired,
- previewSrc: PropTypes.string.isRequired,
+ previewSrc: PropTypes.string,
width: PropTypes.number,
height: PropTypes.number,
+ onClick: PropTypes.func,
}
static defaultProps = {
@@ -24,6 +26,7 @@ export default class ImageLoader extends React.PureComponent {
}
removers = [];
+ canvas = null;
get canvasContext() {
if (!this.canvas) {
@@ -43,11 +46,15 @@ export default class ImageLoader extends React.PureComponent {
}
}
+ componentWillUnmount () {
+ this.removeEventListeners();
+ }
+
loadImage (props) {
this.removeEventListeners();
this.setState({ loading: true, error: false });
Promise.all([
- this.loadPreviewCanvas(props),
+ props.previewSrc && this.loadPreviewCanvas(props),
this.hasSize() && this.loadOriginalImage(props),
].filter(Boolean))
.then(() => {
@@ -118,7 +125,7 @@ export default class ImageLoader extends React.PureComponent {
}
render () {
- const { alt, src, width, height } = this.props;
+ const { alt, src, width, height, onClick } = this.props;
const { loading } = this.state;
const className = classNames('image-loader', {
@@ -128,22 +135,19 @@ export default class ImageLoader extends React.PureComponent {
return (
-
-
- {!loading && (
-
+ ) : (
+
)}
);
diff --git a/app/javascript/flavours/glitch/features/ui/components/media_modal.js b/app/javascript/flavours/glitch/features/ui/components/media_modal.js
index e56147c5bc..6ab6770ed4 100644
--- a/app/javascript/flavours/glitch/features/ui/components/media_modal.js
+++ b/app/javascript/flavours/glitch/features/ui/components/media_modal.js
@@ -3,6 +3,7 @@ import ReactSwipeableViews from 'react-swipeable-views';
import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types';
import ExtendedVideoPlayer from 'flavours/glitch/components/extended_video_player';
+import classNames from 'classnames';
import { defineMessages, injectIntl } from 'react-intl';
import IconButton from 'flavours/glitch/components/icon_button';
import ImmutablePureComponent from 'react-immutable-pure-component';
@@ -26,6 +27,7 @@ export default class MediaModal extends ImmutablePureComponent {
state = {
index: null,
+ navigationHidden: false,
};
handleSwipe = (index) => {
@@ -68,14 +70,21 @@ export default class MediaModal extends ImmutablePureComponent {
return this.state.index !== null ? this.state.index : this.props.index;
}
+ toggleNavigation = () => {
+ this.setState(prevState => ({
+ navigationHidden: !prevState.navigationHidden,
+ }));
+ };
+
render () {
const { media, intl, onClose } = this.props;
+ const { navigationHidden } = this.state;
const index = this.getIndex();
let pagination = [];
- const leftNav = media.size > 1 && ;
- const rightNav = media.size > 1 && ;
+ const leftNav = media.size > 1 && ;
+ const rightNav = media.size > 1 && ;
if (media.size > 1) {
pagination = media.map((item, i) => {
@@ -92,33 +101,77 @@ export default class MediaModal extends ImmutablePureComponent {
const height = image.getIn(['meta', 'original', 'height']) || null;
if (image.get('type') === 'image') {
- return ;
+ return (
+
+ );
} else if (image.get('type') === 'gifv') {
- return ;
+ return (
+
+ );
}
return null;
}).toArray();
+ // you can't use 100vh, because the viewport height is taller
+ // than the visible part of the document in some mobile
+ // browsers when it's address bar is visible.
+ // https://developers.google.com/web/updates/2016/12/url-bar-resizing
+ const swipeableViewsStyle = {
+ width: '100%',
+ height: '100%',
+ };
+
const containerStyle = {
alignItems: 'center', // center vertically
};
+ const navigationClassName = classNames('media-modal__navigation', {
+ 'media-modal__navigation--hidden': navigationHidden,
+ });
+
return (
- {leftNav}
-
-
-
-
+
+
{content}
-
-
- {rightNav}
+
+
+ {leftNav}
+ {rightNav}
+
+
);
}
diff --git a/app/javascript/flavours/glitch/features/ui/components/video_modal.js b/app/javascript/flavours/glitch/features/ui/components/video_modal.js
index 4412fd0f79..e0cb7fc095 100644
--- a/app/javascript/flavours/glitch/features/ui/components/video_modal.js
+++ b/app/javascript/flavours/glitch/features/ui/components/video_modal.js
@@ -16,7 +16,7 @@ export default class VideoModal extends ImmutablePureComponent {
const { media, time, onClose } = this.props;
return (
-
+