Zoomable image viewer in Markdown (posts and comments)

## Issue
4899: Ability to expand images in markdown posts for viewing
This commit is contained in:
infiinte-persistence 2021-01-27 11:24:14 +08:00 committed by Sean Yesmunt
parent 153ebbca63
commit 7419fefa2d
11 changed files with 89 additions and 0 deletions

View file

@ -8,6 +8,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Added
- Zoomable image viewer in Markdown (posts and comments) _community pr!_ ([#5387](https://github.com/lbryio/lbry-desktop/pull/5387))
### Changed
### Fixed

View file

@ -162,6 +162,7 @@
"raw-loader": "^2.0.0",
"rc-progress": "^2.0.6",
"react": "^16.8.2",
"react-awesome-lightbox": "^1.7.3",
"react-confetti": "^4.0.1",
"react-dom": "^16.8.2",
"react-draggable": "^3.3.0",

View file

@ -12,6 +12,7 @@ import MarkdownLink from 'component/markdownLink';
import defaultSchema from 'hast-util-sanitize/lib/github.json';
import { formatedLinks, inlineLinks } from 'util/remark-lbry';
import { formattedTimestamp, inlineTimestamp } from 'util/remark-timestamp';
import ZoomableImage from 'component/zoomableImage';
type SimpleTextProps = {
children?: React.Node,
@ -33,10 +34,16 @@ type MarkdownProps = {
isMarkdownPost?: boolean,
};
// ****************************************************************************
// ****************************************************************************
const SimpleText = (props: SimpleTextProps) => {
return <span>{props.children}</span>;
};
// ****************************************************************************
// ****************************************************************************
const SimpleLink = (props: SimpleLinkProps) => {
const { title, children, href } = props;
@ -70,6 +77,9 @@ const SimpleLink = (props: SimpleLinkProps) => {
return <a title={title}>{children}</a>;
};
// ****************************************************************************
// ****************************************************************************
// Use github sanitation schema
const schema = { ...defaultSchema };
@ -79,6 +89,9 @@ schema.attributes.a.push('embed');
const REPLACE_REGEX = /(<iframe\s+src=["'])(.*?(?=))(["']\s*><\/iframe>)/g;
// ****************************************************************************
// ****************************************************************************
const MarkdownPreview = (props: MarkdownProps) => {
const { content, strip, simpleLinks, noDataStore, className, parentCommentId, isMarkdownPost } = props;
const strippedContent = content
@ -116,6 +129,7 @@ const MarkdownPreview = (props: MarkdownProps) => {
),
// Workaraund of remarkOptions.Fragment
div: React.Fragment,
img: ZoomableImage,
},
};

View file

@ -0,0 +1,9 @@
import { connect } from 'react-redux';
import { doOpenModal } from 'redux/actions/app';
import ZoomableImage from './view';
const perform = dispatch => ({
openModal: (modal, props) => dispatch(doOpenModal(modal, props)),
});
export default connect(null, perform)(ZoomableImage);

View file

@ -0,0 +1,20 @@
// @flow
import React from 'react';
import * as MODALS from 'constants/modal_types';
type Props = {
openModal: (string, {}) => void,
};
function ZoomableImage(props: Props) {
const { openModal, ...imgProps } = props;
const onClick = () => {
// $FlowFixMe
openModal(MODALS.VIEW_IMAGE, { src: imgProps.src, title: imgProps.title || imgProps.alt });
};
return <img className="img__zoomable" {...imgProps} onClick={onClick} />;
}
export default ZoomableImage;

View file

@ -44,3 +44,4 @@ export const SYNC_ENABLE = 'SYNC_ENABLE';
export const REMOVE_BLOCKED = 'remove_blocked';
export const IMAGE_UPLOAD = 'image_upload';
export const MOBILE_SEARCH = 'mobile_search';
export const VIEW_IMAGE = 'view_image';

View file

@ -42,6 +42,7 @@ import ModalFileSelection from 'modal/modalFileSelection';
import ModalSyncEnable from 'modal/modalSyncEnable';
import ModalImageUpload from 'modal/modalImageUpload';
import ModalMobileSearch from 'modal/modalMobileSearch';
import ModalViewImage from 'modal/modalViewImage';
type Props = {
modal: { id: string, modalProps: {} },
@ -151,6 +152,8 @@ function ModalRouter(props: Props) {
return <ModalSyncEnable {...modalProps} />;
case MODALS.MOBILE_SEARCH:
return <ModalMobileSearch {...modalProps} />;
case MODALS.VIEW_IMAGE:
return <ModalViewImage {...modalProps} />;
default:
return null;
}

View file

@ -0,0 +1,9 @@
import { connect } from 'react-redux';
import { doHideModal } from 'redux/actions/app';
import ModalViewImage from './view';
const perform = dispatch => ({
closeModal: () => dispatch(doHideModal()),
});
export default connect(null, perform)(ModalViewImage);

View file

@ -0,0 +1,21 @@
// @flow
import React from 'react';
import { Modal } from 'modal/modal';
import Lightbox from 'react-awesome-lightbox';
import 'react-awesome-lightbox/build/style.css';
type Props = {
src: string,
title: String,
closeModal: () => void,
};
export default function ModalMobileSearch(props: Props) {
const { src, title, closeModal } = props;
return (
<Modal onAborted={closeModal} isOpen type="custom">
<Lightbox image={src} title={title} onClose={closeModal} />
</Modal>
);
}

View file

@ -128,6 +128,10 @@
}
}
.img__zoomable {
cursor: pointer; // 'zoom-in' would be ideal, but browser-dependant.
}
// Horizontal Rule
hr {
margin-bottom: 2rem;

View file

@ -9748,6 +9748,11 @@ react-async-script@^1.1.1:
hoist-non-react-statics "^3.3.0"
prop-types "^15.5.0"
react-awesome-lightbox@^1.7.3:
version "1.7.3"
resolved "https://registry.yarnpkg.com/react-awesome-lightbox/-/react-awesome-lightbox-1.7.3.tgz#ee1c00fd4197e0e65bf996aa219eac4d8b6db5a0"
integrity sha512-mSxdL3KGzuh2eR8I00nv9njiolmMoXITuCvfd71DBXK13JW3e+Z/sCMENS9+dngBJU8/m7dR1Ix0W6afS5cFsA==
react-compound-slider@^2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/react-compound-slider/-/react-compound-slider-2.5.0.tgz#99771a3397f4ab00aa2a37f8410da87e6ca2449b"