1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-02 07:27:04 +00:00

[view shared dir] show thumbnail icon & show file with popup for image files (#3224)

This commit is contained in:
llj
2019-04-09 12:32:25 +08:00
committed by Daniel Pan
parent afcc6fe6f1
commit ea24464f0c
3 changed files with 186 additions and 6 deletions

View File

@@ -0,0 +1,57 @@
import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import { gettext } from '../../utils/constants';
import Lightbox from 'react-image-lightbox';
import 'react-image-lightbox/style.css';
const propTypes = {
imageItems: PropTypes.array.isRequired,
imageIndex: PropTypes.number.isRequired,
closeImagePopup: PropTypes.func.isRequired,
moveToPrevImage: PropTypes.func.isRequired,
moveToNextImage: PropTypes.func.isRequired
};
class ImageDialog extends React.Component {
constructor(props) {
super(props);
}
render() {
const imageItems = this.props.imageItems;
const imageIndex = this.props.imageIndex;
const imageItemsLength = imageItems.length;
const imageCaption = imageItemsLength && (
<Fragment>
<span>{gettext('%curr% of %total%').replace('%curr%', imageIndex + 1).replace('%total%', imageItemsLength)}</span>
<br />
<a href={imageItems[imageIndex].url} target="_blank">{gettext('Open in New Tab')}</a>
</Fragment>
);
return (
<Lightbox
mainSrc={imageItems[imageIndex].src}
imageTitle={imageItems[imageIndex].name}
imageCaption={imageCaption}
nextSrc={imageItems[(imageIndex + 1) % imageItemsLength].src}
prevSrc={imageItems[(imageIndex + imageItemsLength - 1) % imageItemsLength].src}
onCloseRequest={this.props.closeImagePopup}
onMovePrevRequest={this.props.moveToPrevImage}
onMoveNextRequest={this.props.moveToNextImage}
imagePadding={70}
imageLoadErrorMessage={gettext('The image could not be loaded.')}
prevLabel={gettext('Previous (Left arrow key)')}
nextLabel={gettext('Next (Right arrow key)')}
closeLabel={gettext('Close (Esc)')}
zoomInLabel={gettext('Zoom in')}
zoomOutLabel={gettext('Zoom out')}
/>
);
}
}
ImageDialog.propTypes = propTypes;
export default ImageDialog;

View File

@@ -166,7 +166,7 @@ class Item extends Component {
const desktopItem = (
<tr onMouseOver={this.handleMouseOver} onMouseOut={this.handleMouseOut}>
<td className="alc">
<td className="text-center">
{
data.thumbnail_url ?
<img className="thumbnail" src={data.thumbnail_url} alt="" /> :
@@ -189,7 +189,7 @@ class Item extends Component {
const mobileItem = (
<tr>
<td className="alc">
<td className="text-center">
{
data.thumbnail_url ?
<img className="thumbnail" src={data.thumbnail_url} alt="" /> :

View File

@@ -3,13 +3,14 @@ import ReactDOM from 'react-dom';
import { Button } from 'reactstrap';
import moment from 'moment';
import Account from './components/common/account';
import { gettext, siteRoot, mediaUrl, logoPath, logoWidth, logoHeight, siteTitle } from './utils/constants';
import { gettext, siteRoot, mediaUrl, logoPath, logoWidth, logoHeight, siteTitle, thumbnailSizeForOriginal } from './utils/constants';
import { Utils } from './utils/utils';
import { seafileAPI } from './utils/seafile-api';
import Loading from './components/loading';
import toaster from './components/toast';
import ModalPortal from './components/modal-portal';
import ShareLinkZipDownloadDialog from './components/dialog/share-link-zip-download-dialog';
import ImageDialog from './components/dialog/image-dialog';
import './css/shared-dir-view.css';
@@ -26,8 +27,13 @@ class SharedDirView extends React.Component {
isLoading: true,
errorMsg: '',
items: [],
isZipDialogOpen: false,
zipFolderPath: ''
zipFolderPath: '',
isImagePopupOpen: false,
imageItems: [],
imageIndex: 0
};
}
@@ -45,6 +51,7 @@ class SharedDirView extends React.Component {
errorMsg: '',
items: items
});
this.getThumbnails();
}).catch((error) => {
let errorMsg = '';
if (error.response) {
@@ -63,6 +70,37 @@ class SharedDirView extends React.Component {
});
}
getThumbnails = () => {
let items = this.state.items.filter((item) => {
return !item.is_dir && Utils.imageCheck(item.file_name) && !item.encoded_thumbnail_src;
});
if (items.length == 0) {
return ;
}
const len = items.length;
const thumbnailSize = 48;
const _this = this;
let getThumbnail = function(i) {
const curItem = items[i];
seafileAPI.getShareLinkThumbnail(token, curItem.file_path, thumbnailSize).then((res) => {
curItem.encoded_thumbnail_src = res.data.encoded_thumbnail_src;
}).catch((error) => {
// do nothing
}).then(() => {
if (i < len - 1) {
getThumbnail(++i);
} else {
// when done, `setState()`
_this.setState({
items: _this.state.items
});
}
});
};
getThumbnail(0);
}
renderPath = () => {
// path: '/', or '/g/'
if (path == '/') {
@@ -104,6 +142,62 @@ class SharedDirView extends React.Component {
});
}
// for image popup
prepareImageItem = (item) => {
const name = item.file_name;
const fileExt = name.substr(name.lastIndexOf('.') + 1).toLowerCase();
const isGIF = fileExt == 'gif';
let src;
const fileURL = `${siteRoot}d/${token}/files/?p=${encodeURIComponent(item.file_path)}`;
if (!isGIF) {
src = `${siteRoot}thumbnail/${token}/${thumbnailSizeForOriginal}${Utils.encodePath(item.file_path)}`;
} else {
src = `${fileURL}&raw=1`;
}
return {
'name': name,
'url': fileURL,
'src': src
};
}
showImagePopup = (curItem) => {
const items = this.state.items.filter((item) => {
return !item.is_dir && Utils.imageCheck(item.file_name);
});
const imageItems = items.map((item) => {
return this.prepareImageItem(item);
});
this.setState({
isImagePopupOpen: true,
imageItems: imageItems,
imageIndex: items.indexOf(curItem)
});
}
closeImagePopup = () => {
this.setState({
isImagePopupOpen: false
});
}
moveToPrevImage = () => {
const imageItemsLength = this.state.imageItems.length;
this.setState((prevState) => ({
imageIndex: (prevState.imageIndex + imageItemsLength - 1) % imageItemsLength
}));
}
moveToNextImage = () => {
const imageItemsLength = this.state.imageItems.length;
this.setState((prevState) => ({
imageIndex: (prevState.imageIndex + 1) % imageItemsLength
}));
}
render() {
return (
<React.Fragment>
@@ -127,6 +221,7 @@ class SharedDirView extends React.Component {
<Content
data={this.state}
zipDownloadFolder={this.zipDownloadFolder}
showImagePopup={this.showImagePopup}
/>
</div>
</div>
@@ -140,6 +235,17 @@ class SharedDirView extends React.Component {
/>
</ModalPortal>
}
{this.state.isImagePopupOpen &&
<ModalPortal>
<ImageDialog
imageItems={this.state.imageItems}
imageIndex={this.state.imageIndex}
closeImagePopup={this.closeImagePopup}
moveToPrevImage={this.moveToPrevImage}
moveToNextImage={this.moveToNextImage}
/>
</ModalPortal>
}
</React.Fragment>
);
}
@@ -174,6 +280,7 @@ class Content extends React.Component {
key={index}
item={item}
zipDownloadFolder={this.props.zipDownloadFolder}
showImagePopup={this.props.showImagePopup}
/>;
})}
</tbody>
@@ -204,6 +311,16 @@ class Item extends React.Component {
this.props.zipDownloadFolder.bind(this, this.props.item.folder_path)();
}
handleFileNameLinkClick = (e) => {
const item = this.props.item;
if (!Utils.imageCheck(item.file_name)) {
return;
}
e.preventDefault();
this.props.showImagePopup(item);
}
render() {
const item = this.props.item;
const { isIconShown } = this.state;
@@ -228,11 +345,17 @@ class Item extends React.Component {
);
} else {
const fileURL = `${siteRoot}d/${token}/files/?p=${encodeURIComponent(item.file_path)}`;
const thumbnailURL = item.encoded_thumbnail_src ? `${siteRoot}${item.encoded_thumbnail_src}` : '';
return (
<tr onMouseOver={this.handleMouseOver} onMouseOut={this.handleMouseOut}>
<td className="text-center"><img src={Utils.getFileIconUrl(item.file_name)} alt="" width="24" /></td>
<td className="text-center">
{thumbnailURL ?
<img className="thumbnail" src={thumbnailURL} alt="" /> :
<img src={Utils.getFileIconUrl(item.file_name)} alt="" width="24" />
}
</td>
<td>
<a href={fileURL}>{item.file_name}</a>
<a href={fileURL} onClick={this.handleFileNameLinkClick}>{item.file_name}</a>
</td>
<td>{Utils.bytesToSize(item.size)}</td>
<td>{moment(item.last_modified).format('YYYY-MM-DD')}</td>