1
0
Fork 0
mirror of https://github.com/muerwre/vault-frontend.git synced 2025-04-25 12:56:41 +07:00

photoswipe element

This commit is contained in:
Fedor Katurov 2020-04-20 18:04:09 +07:00
parent 55c806ce21
commit 19aeb8a334
16 changed files with 260 additions and 58 deletions

View file

@ -0,0 +1,121 @@
import React, { FC, useRef, useEffect, useMemo, useCallback } from 'react';
import { connect } from 'react-redux';
import PhotoSwipeJs from 'photoswipe/dist/photoswipe.js';
import PhotoSwipeUI_Default from 'photoswipe/dist/photoswipe-ui-default.js';
import 'photoswipe/dist/photoswipe.css';
import 'photoswipe/dist/default-skin/default-skin.css';
import { IState } from '~/redux/store';
import { selectModal } from '~/redux/modal/selectors';
import { getURL } from '~/utils/dom';
import { PRESETS } from '~/constants/urls';
import * as MODAL_ACTIONS from '~/redux/modal/actions';
import styles from './styles.scss';
import classNames from 'classnames';
const mapStateToProps = (state: IState) => ({
photoswipe: selectModal(state).photoswipe,
});
const mapDispatchToProps = {
modalSetShown: MODAL_ACTIONS.modalSetShown,
};
type Props = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & {};
const PhotoSwipeUnconnected: FC<Props> = ({ photoswipe, modalSetShown }) => {
let ref = useRef<HTMLDivElement>(null);
const items = useMemo(
() =>
photoswipe.images.map(image => ({
src: getURL(image, window.innerWidth < 768 ? PRESETS[900] : ''),
})),
[photoswipe.images]
);
const closeModal = useCallback(() => modalSetShown(false), [modalSetShown]);
useEffect(() => {
new Promise(async resolve => {
const images = await Promise.all(
items.map(
item =>
new Promise(resolveImage => {
const img = new Image();
img.onload = () => {
resolveImage({
src: item.src,
h: img.naturalHeight,
w: img.naturalWidth,
});
};
img.onerror = () => {
resolveImage({});
};
img.src = item.src;
})
)
);
resolve(images);
}).then(images => {
const ps = new PhotoSwipeJs(ref.current, PhotoSwipeUI_Default, images, {
index: photoswipe.index || 0,
closeOnScroll: false,
history: false,
});
ps.init();
ps.listen('destroy', closeModal);
ps.listen('close', closeModal);
});
}, [items, photoswipe.index]);
return (
<div className="pswp" tabIndex={-1} role="dialog" aria-hidden="true" ref={ref}>
<div className={classNames('pswp__bg', styles.bg)} />
<div className="pswp__scroll-wrap">
<div className="pswp__container">
<div className="pswp__item" />
<div className="pswp__item" />
<div className="pswp__item" />
</div>
<div className="pswp__ui pswp__ui--hidden">
<div className={classNames('pswp__top-bar', styles.bar)}>
<div className="pswp__counter" />
<button className="pswp__button pswp__button--close" title="Close (Esc)" />
<button className="pswp__button pswp__button--fs" title="Toggle fullscreen" />
<button className="pswp__button pswp__button--zoom" title="Zoom in/out" />
<div className="pswp__preloader">
<div className="pswp__preloader__icn">
<div className="pswp__preloader__cut">
<div className="pswp__preloader__donut" />
</div>
</div>
</div>
</div>
<div className="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
<div className="pswp__share-tooltip" />
</div>
<button
className="pswp__button pswp__button--arrow--left"
title="Previous (arrow left)"
/>
<button className="pswp__button pswp__button--arrow--right" title="Next (arrow right)" />
<div className="pswp__caption">
<div className="pswp__caption__center" />
</div>
</div>
</div>
</div>
);
};
const PhotoSwipe = connect(mapStateToProps, mapDispatchToProps)(PhotoSwipeUnconnected);
export { PhotoSwipe };

View file

@ -0,0 +1,7 @@
.bg {
background-color: transparent;
}
.bar {
background-color: transparent !important;
}

View file

@ -10,11 +10,9 @@ import { Group } from '~/components/containers/Group';
import { Padder } from '~/components/containers/Padder';
import { NodeNoComments } from '~/components/node/NodeNoComments';
import { NodeRelated } from '~/components/node/NodeRelated';
import * as styles from './styles.scss';
import { NodeComments } from '~/components/node/NodeComments';
import { NodeTags } from '~/components/node/NodeTags';
import { NODE_COMPONENTS, NODE_INLINES } from '~/redux/node/constants';
import * as NODE_ACTIONS from '~/redux/node/actions';
import { selectUser } from '~/redux/auth/selectors';
import pick from 'ramda/es/pick';
import { NodeRelatedPlaceholder } from '~/components/node/NodeRelated/placeholder';
@ -23,7 +21,12 @@ import { NodeCommentForm } from '~/components/node/NodeCommentForm';
import { Sticky } from '~/components/containers/Sticky';
import { Footer } from '~/components/main/Footer';
const mapStateToProps = state => ({
import * as styles from './styles.scss';
import * as NODE_ACTIONS from '~/redux/node/actions';
import * as MODAL_ACTIONS from '~/redux/modal/actions';
import { IState } from '~/redux/store';
const mapStateToProps = (state: IState) => ({
node: selectNode(state),
user: selectUser(state),
});
@ -39,6 +42,7 @@ const mapDispatchToProps = {
nodeLockComment: NODE_ACTIONS.nodeLockComment,
nodeEditComment: NODE_ACTIONS.nodeEditComment,
nodeLoadMoreComments: NODE_ACTIONS.nodeLoadMoreComments,
modalShowPhotoswipe: MODAL_ACTIONS.modalShowPhotoswipe,
};
type IProps = ReturnType<typeof mapStateToProps> &
@ -71,6 +75,7 @@ const NodeLayoutUnconnected: FC<IProps> = memo(
nodeLockComment,
nodeEditComment,
nodeLoadMoreComments,
modalShowPhotoswipe,
}) => {
const [layout, setLayout] = useState({});
@ -108,7 +113,8 @@ const NodeLayoutUnconnected: FC<IProps> = memo(
return (
<Card className={styles.node} seamless>
{block && createElement(block, { node, is_loading, updateLayout, layout })}
{block &&
createElement(block, { node, is_loading, updateLayout, layout, modalShowPhotoswipe })}
<NodePanel
node={pick(['title', 'user', 'is_liked', 'is_heroic', 'deleted_at', 'created_at'], node)}
@ -137,6 +143,7 @@ const NodeLayoutUnconnected: FC<IProps> = memo(
is_loading,
updateLayout,
layout,
modalShowPhotoswipe,
})}
</div>
)}