diff options
author | Joram Wilander <jwawilander@gmail.com> | 2016-08-18 18:38:38 -0400 |
---|---|---|
committer | Corey Hulen <corey@hulen.com> | 2016-08-18 14:38:38 -0800 |
commit | 3289c856130c4d1956dda9229fb3c6a060655b1a (patch) | |
tree | 1c3f180c9ef1a8c5a8146e63c68e82cdf3e175d0 /webapp/components/pdf_preview.jsx | |
parent | ed6b69aab3136b2a5bcddbab77659640cd4d6534 (diff) | |
download | chat-3289c856130c4d1956dda9229fb3c6a060655b1a.tar.gz chat-3289c856130c4d1956dda9229fb3c6a060655b1a.tar.bz2 chat-3289c856130c4d1956dda9229fb3c6a060655b1a.zip |
PLT-3642 Add PDF previewer (#3812)
* Added a PDF previewer
* PLT-3900 - Improving UI for the pdf max pages (#3800)
Diffstat (limited to 'webapp/components/pdf_preview.jsx')
-rw-r--r-- | webapp/components/pdf_preview.jsx | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/webapp/components/pdf_preview.jsx b/webapp/components/pdf_preview.jsx new file mode 100644 index 000000000..fd1ca7758 --- /dev/null +++ b/webapp/components/pdf_preview.jsx @@ -0,0 +1,189 @@ +// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import FileInfoPreview from './file_info_preview.jsx'; + +import * as Utils from 'utils/utils.jsx'; + +import loadingGif from 'images/load.gif'; + +import React from 'react'; +import PDFJS from 'pdfjs-dist'; +import {FormattedMessage} from 'react-intl'; + +const MAX_PDF_PAGES = 5; + +export default class PDFPreview extends React.Component { + constructor(props) { + super(props); + + this.updateStateFromProps = this.updateStateFromProps.bind(this); + this.onDocumentLoad = this.onDocumentLoad.bind(this); + this.onPageLoad = this.onPageLoad.bind(this); + this.renderPDFPage = this.renderPDFPage.bind(this); + + this.pdfPagesRendered = {}; + + this.state = { + pdf: null, + pdfPages: {}, + pdfPagesLoaded: {}, + numPages: 0, + loading: true, + success: false + }; + } + + componentDidMount() { + this.updateStateFromProps(this.props); + } + + componentWillReceiveProps(nextProps) { + if (this.props.fileUrl !== nextProps.fileUrl) { + this.updateStateFromProps(nextProps); + this.pdfPagesRendered = {}; + } + } + + componentDidUpdate() { + if (this.state.success) { + for (let i = 0; i < this.state.numPages; i++) { + this.renderPDFPage(i); + } + } + } + + renderPDFPage(pageIndex) { + if (this.pdfPagesRendered[pageIndex] || !this.state.pdfPagesLoaded[pageIndex]) { + return; + } + + const canvas = this.refs['pdfCanvas' + pageIndex]; + const context = canvas.getContext('2d'); + const viewport = this.state.pdfPages[pageIndex].getViewport(1); + + canvas.height = viewport.height; + canvas.width = viewport.width; + + const renderContext = { + canvasContext: context, + viewport + }; + + this.state.pdfPages[pageIndex].render(renderContext); + this.pdfPagesRendered[pageIndex] = true; + } + + updateStateFromProps(props) { + this.setState({ + pdf: null, + pdfPages: {}, + pdfPagesLoaded: {}, + numPages: 0, + loading: true, + success: false + }); + + PDFJS.getDocument(window.mm_config.SiteURL + props.fileUrl).then(this.onDocumentLoad); + } + + onDocumentLoad(pdf) { + const numPages = pdf.numPages <= MAX_PDF_PAGES ? pdf.numPages : MAX_PDF_PAGES; + this.setState({pdf, numPages}); + for (let i = 1; i <= pdf.numPages; i++) { + pdf.getPage(i).then(this.onPageLoad); + } + } + + onPageLoad(page) { + const pdfPages = Object.assign({}, this.state.pdfPages); + pdfPages[page.pageIndex] = page; + + const pdfPagesLoaded = Object.assign({}, this.state.pdfPagesLoaded); + pdfPagesLoaded[page.pageIndex] = true; + + this.setState({pdfPages, pdfPagesLoaded}); + + if (page.pageIndex === 0) { + this.setState({success: true, loading: false}); + } + } + + static support(filename) { + const fileInfo = Utils.splitFileLocation(filename); + const ext = fileInfo.ext; + if (!ext) { + return false; + } + + if (ext === 'pdf') { + return true; + } + + return false; + } + + render() { + if (this.state.loading) { + return ( + <div className='view-image__loading'> + <img + className='loader-image' + src={loadingGif} + /> + </div> + ); + } + + if (!this.state.success) { + return ( + <FileInfoPreview + filename={this.props.filename} + fileUrl={this.props.fileUrl} + fileInfo={this.props.fileInfo} + formatMessage={this.props.formatMessage} + /> + ); + } + + const pdfCanvases = []; + for (let i = 0; i < this.state.numPages; i++) { + pdfCanvases.push( + <canvas + ref={'pdfCanvas' + i} + key={'previewpdfcanvas' + i} + /> + ); + + if (i < this.state.numPages - 1 && this.state.numPages > 1) { + pdfCanvases.push( + <div className='pdf-preview-spacer'/> + ); + } + } + + if (this.state.pdf.numPages > MAX_PDF_PAGES) { + pdfCanvases.push( + <div className='pdf-max-pages'> + <FormattedMessage + id='pdf_preview.max_pages' + defaultMessage='PDF previews only show the first five pages.' + /> + </div> + ); + } + + return ( + <div className='post-code'> + {pdfCanvases} + </div> + ); + } +} + +PDFPreview.propTypes = { + filename: React.PropTypes.string.isRequired, + fileUrl: React.PropTypes.string.isRequired, + fileInfo: React.PropTypes.object.isRequired, + formatMessage: React.PropTypes.func.isRequired +}; |