diff --git a/frontend/src/components/dir-view-mode/dir-column-nav.js b/frontend/src/components/dir-view-mode/dir-column-nav.js index 88567bc82f..30bac069c7 100644 --- a/frontend/src/components/dir-view-mode/dir-column-nav.js +++ b/frontend/src/components/dir-view-mode/dir-column-nav.js @@ -9,12 +9,15 @@ import Move from '../../components/dialog/move-dirent-dialog'; import CreateFolder from '../../components/dialog/create-folder-dialog'; import CreateFile from '../../components/dialog/create-file-dialog'; import ImageDialog from '../../components/dialog/image-dialog'; -import { fileServerRoot, gettext, siteRoot, thumbnailSizeForOriginal } from '../../utils/constants'; +import { fileServerRoot, gettext, siteRoot, thumbnailSizeForOriginal, thumbnailDefaultSize } from '../../utils/constants'; import { Utils } from '../../utils/utils'; import TextTranslation from '../../utils/text-translation'; import TreeSection from '../../components/tree-section'; import DirViews from './dir-views'; import DirOthers from './dir-others'; +import imageAPI from '../../utils/image-api'; +import { seafileAPI } from '../../utils/seafile-api'; +import toaster from '../toast'; import './dir-column-nav.css'; @@ -40,6 +43,7 @@ const propTypes = { selectedDirentList: PropTypes.array.isRequired, onItemsMove: PropTypes.func.isRequired, getMenuContainerSize: PropTypes.func, + updateDirent: PropTypes.func, direntList: PropTypes.array }; @@ -319,6 +323,37 @@ class DirColumnNav extends React.Component { } }; + handleError = (error) => { + toaster.danger(Utils.getErrorMsg(error)); + }; + + rotateImage = (imageIndex, angle) => { + if (imageIndex >= 0 && angle !== 0) { + let { repoID } = this.props; + let imageName = this.state.imageNodeItems[imageIndex].name; + let path = this.state.opNode.path; + imageAPI.rotateImage(repoID, path, 360 - angle).then((res) => { + seafileAPI.createThumbnail(repoID, path, thumbnailDefaultSize).then((res) => { + // Generate a unique query parameter to bust the cache + const cacheBuster = new Date().getTime(); + const newThumbnailSrc = `${res.data.encoded_thumbnail_src}?t=${cacheBuster}`; + this.setState((prevState) => { + const updatedImageItems = [...prevState.imageNodeItems]; + updatedImageItems[imageIndex].src = newThumbnailSrc; + return { imageNodeItems: updatedImageItems }; + }); + // Update the thumbnail URL with the cache-busting query parameter + const item = this.props.direntList.find((item) => item.name === imageName); + this.props.updateDirent(item, 'encoded_thumbnail_src', newThumbnailSrc); + }).catch(error => { + this.handleError(error); + }); + }).catch(error => { + this.handleError(error); + }); + } + }; + stopTreeScrollPropagation = (e) => { e.stopPropagation(); }; @@ -457,6 +492,7 @@ class DirColumnNav extends React.Component { moveToPrevImage={this.moveToPrevImage} moveToNextImage={this.moveToNextImage} onDeleteImage={this.deleteImage} + onRotateImage={this.rotateImage} /> )} diff --git a/frontend/src/components/dir-view-mode/dir-column-view.js b/frontend/src/components/dir-view-mode/dir-column-view.js index 5afdf4367b..44c84c8632 100644 --- a/frontend/src/components/dir-view-mode/dir-column-view.js +++ b/frontend/src/components/dir-view-mode/dir-column-view.js @@ -175,6 +175,7 @@ class DirColumnView extends React.Component { onItemsMove={this.props.onItemsMove} getMenuContainerSize={this.getMenuContainerSize} direntList={this.props.direntList} + updateDirent={this.props.updateDirent} /> { + toaster.danger(Utils.getErrorMsg(error)); + }; + onLockItem = (currentObject) => { let repoID = this.props.repoID; let filePath = this.getDirentPath(currentObject); @@ -523,8 +527,7 @@ class DirentGridView extends React.Component { let lockName = username.split('@'); this.props.updateDirent(currentObject, 'lock_owner_name', lockName[0]); }).catch(error => { - let errMessage = Utils.getErrorMsg(error); - toaster.danger(errMessage); + this.handleError(error); }); }; @@ -538,8 +541,7 @@ class DirentGridView extends React.Component { let lockName = username.split('@'); this.props.updateDirent(currentObject, 'lock_owner_name', lockName[0]); }).catch(error => { - let errMessage = Utils.getErrorMsg(error); - toaster.danger(errMessage); + this.handleError(error); }); }; @@ -551,8 +553,7 @@ class DirentGridView extends React.Component { this.props.updateDirent(currentObject, 'locked_by_me', false); this.props.updateDirent(currentObject, 'lock_owner_name', ''); }).catch(error => { - let errMessage = Utils.getErrorMsg(error); - toaster.danger(errMessage); + this.handleError(error); }); }; @@ -646,29 +647,27 @@ class DirentGridView extends React.Component { rotateImage = (imageIndex, angle) => { if (imageIndex >= 0 && angle !== 0) { - const path = this.state.path === '/' ? this.props.path + this.state.imageItems[imageIndex].name : this.props.path + '/' + this.state.imageItems[imageIndex].name; - imageAPI.rotateImage(this.props.repoID, path, 360 - angle).then((res) => { - seafileAPI.createThumbnail(this.props.repoID, path, thumbnailDefaultSize).then((res) => { + let { repoID } = this.props; + let imageName = this.state.imageItems[imageIndex].name; + let path = Utils.joinPath(this.props.path, imageName); + imageAPI.rotateImage(repoID, path, 360 - angle).then((res) => { + seafileAPI.createThumbnail(repoID, path, thumbnailDefaultSize).then((res) => { // Generate a unique query parameter to bust the cache const cacheBuster = new Date().getTime(); const newThumbnailSrc = `${res.data.encoded_thumbnail_src}?t=${cacheBuster}`; - this.setState((prevState) => { const updatedImageItems = [...prevState.imageItems]; updatedImageItems[imageIndex].src = newThumbnailSrc; return { imageItems: updatedImageItems }; }); - // Update the thumbnail URL with the cache-busting query parameter - const item = this.props.direntList.find((item) => item.name === this.state.imageItems[imageIndex].name); + const item = this.props.direntList.find((item) => item.name === imageName); this.props.updateDirent(item, 'encoded_thumbnail_src', newThumbnailSrc); }).catch(error => { - let errMessage = Utils.getErrorMsg(error); - toaster.danger(errMessage); + this.handleError(error); }); }).catch(error => { - let errMessage = Utils.getErrorMsg(error); - toaster.danger(errMessage); + this.handleError(error); }); } }; diff --git a/frontend/src/components/dirent-list-view/dirent-list-view.js b/frontend/src/components/dirent-list-view/dirent-list-view.js index 226640775c..b8fb044ea2 100644 --- a/frontend/src/components/dirent-list-view/dirent-list-view.js +++ b/frontend/src/components/dirent-list-view/dirent-list-view.js @@ -1,6 +1,6 @@ import React, { Fragment } from 'react'; import PropTypes from 'prop-types'; -import { siteRoot, gettext, username, enableSeadoc, thumbnailSizeForOriginal, fileServerRoot } from '../../utils/constants'; +import { siteRoot, gettext, username, enableSeadoc, thumbnailSizeForOriginal, thumbnailDefaultSize, fileServerRoot } from '../../utils/constants'; import { Utils } from '../../utils/utils'; import TextTranslation from '../../utils/text-translation'; import URLDecorator from '../../utils/url-decorator'; @@ -19,6 +19,8 @@ import { hideMenu, showMenu } from '../context-menu/actions'; import DirentsDraggedPreview from '../draggable/dirents-dragged-preview'; import { EVENT_BUS_TYPE } from '../common/event-bus-type'; import EmptyTip from '../empty-tip'; +import imageAPI from '../../utils/image-api'; +import { seafileAPI } from '../../utils/seafile-api'; const propTypes = { path: PropTypes.string.isRequired, @@ -238,6 +240,37 @@ class DirentListView extends React.Component { })); }; + handleError = (error) => { + toaster.danger(Utils.getErrorMsg(error)); + }; + + rotateImage = (imageIndex, angle) => { + if (imageIndex >= 0 && angle !== 0) { + let { repoID } = this.props; + let imageName = this.state.imageItems[imageIndex].name; + let path = Utils.joinPath(this.props.path, imageName); + imageAPI.rotateImage(repoID, path, 360 - angle).then((res) => { + seafileAPI.createThumbnail(repoID, path, thumbnailDefaultSize).then((res) => { + // Generate a unique query parameter to bust the cache + const cacheBuster = new Date().getTime(); + const newThumbnailSrc = `${res.data.encoded_thumbnail_src}?t=${cacheBuster}`; + this.setState((prevState) => { + const updatedImageItems = [...prevState.imageItems]; + updatedImageItems[imageIndex].src = newThumbnailSrc; + return { imageItems: updatedImageItems }; + }); + // Update the thumbnail URL with the cache-busting query parameter + const item = this.props.direntList.find((item) => item.name === imageName); + this.props.updateDirent(item, 'encoded_thumbnail_src', newThumbnailSrc); + }).catch(error => { + this.handleError(error); + }); + }).catch(error => { + this.handleError(error); + }); + } + }; + closeImagePopup = () => { this.setState({ isImagePopupOpen: false }); }; @@ -772,6 +805,7 @@ class DirentListView extends React.Component { moveToPrevImage={this.moveToPrevImage} moveToNextImage={this.moveToNextImage} onDeleteImage={this.deleteImage} + onRotateImage={this.rotateImage} /> )}