diff --git a/frontend/src/components/dialog/image-dialog.js b/frontend/src/components/dialog/image-dialog.js index 855763551b..32c990deda 100644 --- a/frontend/src/components/dialog/image-dialog.js +++ b/frontend/src/components/dialog/image-dialog.js @@ -47,14 +47,20 @@ class ImageDialog extends React.Component { const imageItemsLength = imageItems.length; const name = imageItems[imageIndex].name; const imageTitle = `${name} (${imageIndex + 1}/${imageItemsLength})`; + const mainImg = imageItems[imageIndex]; + const nextImg = imageItems[(imageIndex + 1) % imageItemsLength]; + const prevImg = imageItems[(imageIndex + imageItemsLength - 1) % imageItemsLength]; + const mainSrc = mainImg.thumbnail || mainImg.src; + const nextSrc = nextImg.thumbnail || nextImg.src; + const prevSrc = prevImg.thumbnail || prevImg.src; return ( item.path.split('/').pop() === name), }; }; diff --git a/frontend/src/components/dirent-detail/dirent-details/index.js b/frontend/src/components/dirent-detail/dirent-details/index.js index 374a38bc98..8fa53a5a81 100644 --- a/frontend/src/components/dirent-detail/dirent-details/index.js +++ b/frontend/src/components/dirent-detail/dirent-details/index.js @@ -1,6 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { siteRoot } from '../../../utils/constants'; +import { siteRoot, thumbnailSizeForGrid } from '../../../utils/constants'; import { seafileAPI } from '../../../utils/seafile-api'; import { Utils } from '../../../utils/utils'; import toaster from '../../toast'; @@ -25,7 +25,10 @@ class DirentDetails extends React.Component { updateDetail = (repoID, dirent, direntPath) => { const apiName = dirent.type === 'file' ? 'getFileInfo' : 'getDirInfo'; seafileAPI[apiName](repoID, direntPath).then(res => { - this.setState(({ direntDetail: res.data, dirent })); + this.setState(({ + direntDetail: res.data, + dirent, + })); }).catch(error => { const errMessage = Utils.getErrorMsg(error); toaster.danger(errMessage); @@ -59,11 +62,12 @@ class DirentDetails extends React.Component { UNSAFE_componentWillReceiveProps(nextProps) { const { dirent, path, repoID, currentRepoInfo, repoTags, fileTags } = this.props; if (!ObjectUtils.isSameObject(currentRepoInfo, nextProps.currentRepoInfo) || - !ObjectUtils.isSameObject(dirent, nextProps.dirent) || - JSON.stringify(repoTags || []) !== JSON.stringify(nextProps.repoTags || []) || - JSON.stringify(fileTags || []) !== JSON.stringify(nextProps.fileTags || []) || - path !== nextProps.path || - repoID !== nextProps.repoID) { + !ObjectUtils.isSameObject(dirent, nextProps.dirent) || + JSON.stringify(repoTags || []) !== JSON.stringify(nextProps.repoTags || []) || + JSON.stringify(fileTags || []) !== JSON.stringify(nextProps.fileTags || []) || + path !== nextProps.path || + repoID !== nextProps.repoID + ) { this.setState({ dirent: null }, () => { this.loadDetail(nextProps.repoID, nextProps.dirent, nextProps.path); }); @@ -73,12 +77,10 @@ class DirentDetails extends React.Component { renderImage = () => { const { dirent } = this.state; if (!dirent) return null; - // let bigIconUrl = Utils.getDirentIcon(dirent, true); const isImg = Utils.imageCheck(dirent.name); - // const isVideo = Utils.videoCheck(dirent.name); if (!isImg) return null; const { repoID, path } = this.props; - const bigIconUrl = `${siteRoot}thumbnail/${repoID}/1024` + Utils.encodePath(`${path === '/' ? '' : path}/${dirent.name}`); + const bigIconUrl = `${siteRoot}thumbnail/${repoID}/${thumbnailSizeForGrid}` + Utils.encodePath(`${path === '/' ? '' : path}/${dirent.name}`); return (
diff --git a/frontend/src/components/dirent-grid-view/dirent-grid-view.js b/frontend/src/components/dirent-grid-view/dirent-grid-view.js index 250db3b61d..aecf9511d0 100644 --- a/frontend/src/components/dirent-grid-view/dirent-grid-view.js +++ b/frontend/src/components/dirent-grid-view/dirent-grid-view.js @@ -1,6 +1,6 @@ import React, { Fragment } from 'react'; import PropTypes from 'prop-types'; -import { siteRoot, username, enableSeadoc } from '../../utils/constants'; +import { siteRoot, username, enableSeadoc, thumbnailDefaultSize, thumbnailSizeForOriginal } from '../../utils/constants'; import { Utils } from '../../utils/utils'; import { seafileAPI } from '../../utils/seafile-api'; import URLDecorator from '../../utils/url-decorator'; @@ -566,14 +566,13 @@ class DirentGridView extends React.Component { const name = item.name; const repoID = this.props.repoID; const path = Utils.encodePath(Utils.joinPath(this.props.path, name)); - const cacheBuster = new Date().getTime(); - const src = `${siteRoot}repo/${repoID}/raw${path}?t=${cacheBuster}`; return { 'name': name, 'url': `${siteRoot}lib/${repoID}/file${path}`, - 'src': src + 'thumbnail': `${siteRoot}thumbnail/${repoID}/${thumbnailSizeForOriginal}${path}`, + 'src': `${siteRoot}repo/${repoID}/raw${path}?t=${cacheBuster}`, }; }; @@ -630,7 +629,7 @@ class DirentGridView extends React.Component { 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, 48).then((res) => { + seafileAPI.createThumbnail(this.props.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}`; 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 dec9f523f7..cbfc1433f1 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 } from '../../utils/constants'; +import { siteRoot, gettext, username, enableSeadoc, thumbnailSizeForOriginal } from '../../utils/constants'; import { Utils } from '../../utils/utils'; import TextTranslation from '../../utils/text-translation'; import URLDecorator from '../../utils/url-decorator'; @@ -182,12 +182,12 @@ class DirentListView extends React.Component { const name = item.name; const repoID = this.props.repoID; const path = Utils.encodePath(Utils.joinPath(this.props.path, name)); - const src = `${siteRoot}repo/${repoID}/raw${path}`; return { 'name': name, 'url': `${siteRoot}lib/${repoID}/file${path}`, - 'src': src + 'thumbnail': `${siteRoot}thumbnail/${repoID}/${thumbnailSizeForOriginal}${path}`, + 'src': `${siteRoot}repo/${repoID}/raw${path}`, }; }; diff --git a/frontend/src/metadata/metadata-view/components/cell-editor/file-name-editor.js b/frontend/src/metadata/metadata-view/components/cell-editor/file-name-editor.js index a11645a2da..32e3b908e7 100644 --- a/frontend/src/metadata/metadata-view/components/cell-editor/file-name-editor.js +++ b/frontend/src/metadata/metadata-view/components/cell-editor/file-name-editor.js @@ -27,6 +27,7 @@ const FileNameEditor = ({ column, record, table, onCommitCancel }) => { return { name: fileName, url: `${siteRoot}lib/${repoID}/file${path}`, + thumbnail: `${siteRoot}thumbnail/${repoID}/${thumbnailSizeForOriginal}${path}`, src: src, }; }); diff --git a/frontend/src/metadata/metadata-view/components/view/gallery/index.js b/frontend/src/metadata/metadata-view/components/view/gallery/index.js index 02a05cb323..ffa0dd396b 100644 --- a/frontend/src/metadata/metadata-view/components/view/gallery/index.js +++ b/frontend/src/metadata/metadata-view/components/view/gallery/index.js @@ -2,7 +2,7 @@ import React, { useMemo, useState, useEffect, useRef, useCallback } from 'react' import { useMetadata } from '../../../hooks'; import { Utils } from '../../../../../utils/utils'; import { PRIVATE_COLUMN_KEY } from '../../../_basic'; -import { siteRoot } from '../../../../../utils/constants'; +import { siteRoot, thumbnailSizeForGrid } from '../../../../../utils/constants'; import { EVENT_BUS_TYPE } from '../../../constants'; import './index.css'; @@ -74,9 +74,7 @@ const Gallery = () => { const parentDir = item[PRIVATE_COLUMN_KEY.PARENT_DIR]; const path = Utils.encodePath(Utils.joinPath(parentDir, fileName)); const date = item[PRIVATE_COLUMN_KEY.FILE_CTIME].split('T')[0]; - - const src = `${siteRoot}thumbnail/${repoID}/192${path}`; - + const src = `${siteRoot}thumbnail/${repoID}/${thumbnailSizeForGrid}${path}`; return { name: fileName, url: `${siteRoot}lib/${repoID}/file${path}`, diff --git a/frontend/src/pages/lib-content-view/lib-content-view.js b/frontend/src/pages/lib-content-view/lib-content-view.js index 581f50c951..255a317ec1 100644 --- a/frontend/src/pages/lib-content-view/lib-content-view.js +++ b/frontend/src/pages/lib-content-view/lib-content-view.js @@ -5,7 +5,7 @@ import moment from 'moment'; import MediaQuery from 'react-responsive'; import { Modal } from 'reactstrap'; import { navigate } from '@gatsbyjs/reach-router'; -import { gettext, siteRoot, username, enableVideoThumbnail, enablePDFThumbnail } from '../../utils/constants'; +import { gettext, siteRoot, username, enableVideoThumbnail, enablePDFThumbnail, thumbnailDefaultSize } from '../../utils/constants'; import { seafileAPI } from '../../utils/seafile-api'; import { Utils } from '../../utils/utils'; import collabServer from '../../utils/collab-server'; @@ -636,11 +636,10 @@ class LibContentView extends React.Component { } const _this = this; const len = items.length; - const thumbnailSize = 48; let getThumbnail = (i) => { const curItem = items[i]; const curItemPath = [path, curItem.name].join('/'); - seafileAPI.createThumbnail(repoID, curItemPath, thumbnailSize).then((res) => { + seafileAPI.createThumbnail(repoID, curItemPath, thumbnailDefaultSize).then((res) => { curItem.encoded_thumbnail_src = res.data.encoded_thumbnail_src; }).catch((error) => { // do nothing diff --git a/frontend/src/pages/starred/starred.js b/frontend/src/pages/starred/starred.js index 9f2ea8c0ba..1ac6307ef6 100644 --- a/frontend/src/pages/starred/starred.js +++ b/frontend/src/pages/starred/starred.js @@ -5,7 +5,7 @@ import { Link, navigate } from '@gatsbyjs/reach-router'; import moment from 'moment'; import { seafileAPI } from '../../utils/seafile-api'; import { Utils } from '../../utils/utils'; -import { gettext, siteRoot, enableVideoThumbnail, enablePDFThumbnail } from '../../utils/constants'; +import { gettext, siteRoot, enableVideoThumbnail, enablePDFThumbnail, thumbnailDefaultSize } from '../../utils/constants'; import EmptyTip from '../../components/empty-tip'; import Loading from '../../components/loading'; import toaster from '../../components/toast'; @@ -87,11 +87,10 @@ class TableBody extends Component { } const len = items.length; - const thumbnailSize = 48; const _this = this; let getThumbnail = function (i) { const curItem = items[i]; - seafileAPI.createThumbnail(curItem.repo_id, curItem.path, thumbnailSize).then((res) => { + seafileAPI.createThumbnail(curItem.repo_id, curItem.path, thumbnailDefaultSize).then((res) => { curItem.encoded_thumbnail_src = res.data.encoded_thumbnail_src; }).catch((error) => { // do nothing diff --git a/frontend/src/shared-dir-view.js b/frontend/src/shared-dir-view.js index 33a9a031c2..8d8e5053f5 100644 --- a/frontend/src/shared-dir-view.js +++ b/frontend/src/shared-dir-view.js @@ -324,6 +324,7 @@ class SharedDirView extends React.Component { return { 'name': name, 'url': fileURL, + 'thumbnail': `${siteRoot}thumbnail/${repoID}/${thumbnailSizeForOriginal}${item.file_path}`, 'src': src }; }; diff --git a/frontend/src/utils/constants.js b/frontend/src/utils/constants.js index 763f5319d5..0c1295af9f 100644 --- a/frontend/src/utils/constants.js +++ b/frontend/src/utils/constants.js @@ -73,6 +73,8 @@ export const enableRepoHistorySetting = window.app.pageOptions.enableRepoHistory export const enableUserCleanTrash = window.app.pageOptions.enableUserCleanTrash; export const isSystemStaff = window.app.pageOptions.isSystemStaff; export const thumbnailSizeForOriginal = window.app.pageOptions.thumbnailSizeForOriginal; +export const thumbnailDefaultSize = window.app.pageOptions.thumbnailDefaultSize; +export const thumbnailSizeForGrid = window.app.pageOptions.thumbnailSizeForGrid; export const repoPasswordMinLength = window.app.pageOptions.repoPasswordMinLength; export const canAddPublicRepo = window.app.pageOptions.canAddPublicRepo; export const canInvitePeople = window.app.pageOptions.canInvitePeople; diff --git a/seahub/api2/endpoints/dir.py b/seahub/api2/endpoints/dir.py index aee5ebca86..787fe32d16 100644 --- a/seahub/api2/endpoints/dir.py +++ b/seahub/api2/endpoints/dir.py @@ -30,7 +30,7 @@ from seahub.base.templatetags.seahub_tags import email2nickname, \ from seahub.utils.repo import parse_repo_perm from seahub.constants import PERMISSION_INVISIBLE -from seahub.settings import ENABLE_VIDEO_THUMBNAIL, THUMBNAIL_ROOT +from seahub.settings import ENABLE_VIDEO_THUMBNAIL, THUMBNAIL_ROOT, THUMBNAIL_DEFAULT_SIZE from seaserv import seafile_api from pysearpc import SearpcError @@ -265,7 +265,7 @@ class DirView(APIView): return api_error(status.HTTP_400_BAD_REQUEST, error_msg) with_thumbnail = to_python_boolean(with_thumbnail) - thumbnail_size = request.GET.get('thumbnail_size', 48) + thumbnail_size = request.GET.get('thumbnail_size', THUMBNAIL_DEFAULT_SIZE) try: thumbnail_size = int(thumbnail_size) except ValueError: diff --git a/seahub/api2/endpoints/share_links.py b/seahub/api2/endpoints/share_links.py index ef87e1d790..1e6c88b8dc 100644 --- a/seahub/api2/endpoints/share_links.py +++ b/seahub/api2/endpoints/share_links.py @@ -48,7 +48,7 @@ from seahub.utils.repo import parse_repo_perm from seahub.thumbnail.utils import get_share_link_thumbnail_src from seahub.settings import SHARE_LINK_EXPIRE_DAYS_MAX, \ SHARE_LINK_EXPIRE_DAYS_MIN, SHARE_LINK_LOGIN_REQUIRED, \ - SHARE_LINK_EXPIRE_DAYS_DEFAULT, \ + SHARE_LINK_EXPIRE_DAYS_DEFAULT, THUMBNAIL_DEFAULT_SIZE, \ ENABLE_VIDEO_THUMBNAIL, \ THUMBNAIL_ROOT, ENABLE_UPLOAD_LINK_VIRUS_CHECK from seahub.wiki.models import Wiki @@ -894,7 +894,7 @@ class ShareLinkDirents(APIView): """ # argument check - thumbnail_size = request.GET.get('thumbnail_size', 48) + thumbnail_size = request.GET.get('thumbnail_size', THUMBNAIL_DEFAULT_SIZE) try: thumbnail_size = int(thumbnail_size) except ValueError: diff --git a/seahub/api2/endpoints/via_repo_token.py b/seahub/api2/endpoints/via_repo_token.py index 80d34be707..18f859c56b 100644 --- a/seahub/api2/endpoints/via_repo_token.py +++ b/seahub/api2/endpoints/via_repo_token.py @@ -100,7 +100,7 @@ class ViaRepoDirView(APIView): return api_error(status.HTTP_400_BAD_REQUEST, error_msg) with_thumbnail = to_python_boolean(with_thumbnail) - thumbnail_size = request.GET.get('thumbnail_size', 48) + thumbnail_size = request.GET.get('thumbnail_size', settings.THUMBNAIL_DEFAULT_SIZE) try: thumbnail_size = int(thumbnail_size) except ValueError: diff --git a/seahub/base/context_processors.py b/seahub/base/context_processors.py index 6c1d1a0d88..c13b90cdbf 100644 --- a/seahub/base/context_processors.py +++ b/seahub/base/context_processors.py @@ -22,9 +22,9 @@ from seahub.settings import SEAFILE_VERSION, SITE_DESCRIPTION, \ SHOW_REPO_DOWNLOAD_BUTTON, SITE_ROOT, ENABLE_GUEST_INVITATION, \ FAVICON_PATH, APPLE_TOUCH_ICON_PATH, THUMBNAIL_SIZE_FOR_ORIGINAL, \ MEDIA_ROOT, SHOW_LOGOUT_ICON, CUSTOM_LOGO_PATH, CUSTOM_FAVICON_PATH, \ - ENABLE_SEAFILE_DOCS, LOGIN_BG_IMAGE_PATH, \ + ENABLE_SEAFILE_DOCS, LOGIN_BG_IMAGE_PATH, THUMBNAIL_DEFAULT_SIZE, \ CUSTOM_LOGIN_BG_PATH, ENABLE_SHARE_LINK_REPORT_ABUSE, \ - PRIVACY_POLICY_LINK, TERMS_OF_SERVICE_LINK, ENABLE_SEADOC + PRIVACY_POLICY_LINK, TERMS_OF_SERVICE_LINK, ENABLE_SEADOC, THUMBNAIL_SIZE_FOR_GRID from seahub.organizations.models import OrgAdminSettings from seahub.organizations.settings import ORG_ENABLE_ADMIN_CUSTOM_LOGO @@ -154,6 +154,8 @@ def base(request): 'enableOnlyoffice': ENABLE_ONLYOFFICE, 'onlyofficeConverterExtensions': ONLYOFFICE_CONVERTER_EXTENSIONS, 'thumbnail_size_for_original': THUMBNAIL_SIZE_FOR_ORIGINAL, + 'thumbnail_size_for_grid': THUMBNAIL_SIZE_FOR_GRID, + 'thumbnail_default_size': THUMBNAIL_DEFAULT_SIZE, 'enable_guest_invitation': ENABLE_GUEST_INVITATION, 'enable_terms_and_conditions': config.ENABLE_TERMS_AND_CONDITIONS, 'show_logout_icon': SHOW_LOGOUT_ICON, diff --git a/seahub/settings.py b/seahub/settings.py index b2a459984a..4aa713eece 100644 --- a/seahub/settings.py +++ b/seahub/settings.py @@ -738,8 +738,8 @@ else: THUMBNAIL_EXTENSION = 'png' # for thumbnail: height(px) and width(px) -THUMBNAIL_DEFAULT_SIZE = 48 -THUMBNAIL_SIZE_FOR_GRID = 192 +THUMBNAIL_DEFAULT_SIZE = 256 +THUMBNAIL_SIZE_FOR_GRID = 512 THUMBNAIL_SIZE_FOR_ORIGINAL = 1024 # size(MB) limit for generate thumbnail diff --git a/seahub/templates/base_for_react.html b/seahub/templates/base_for_react.html index 344dcd656b..eaab1fd686 100644 --- a/seahub/templates/base_for_react.html +++ b/seahub/templates/base_for_react.html @@ -112,6 +112,8 @@ enableUserCleanTrash: {% if enable_user_clean_trash %} true {% else %} false {% endif %}, isSystemStaff: {% if request.user.is_staff %} true {% else %} false {% endif %}, thumbnailSizeForOriginal: {{ thumbnail_size_for_original }}, + thumbnailSizeForGrid: {{ thumbnail_size_for_grid }}, + thumbnailDefaultSize: {{ thumbnail_default_size }}, repoPasswordMinLength: {{repo_password_min_length}}, canAddPublicRepo: {% if can_add_public_repo %} true {% else %} false {% endif %}, enableOCMViaWebdav: {% if enable_ocm_via_webdav %} true {% else %} false {% endif %}, diff --git a/seahub/templates/common_file_view_react.html b/seahub/templates/common_file_view_react.html index ac223584fc..ade46d2eb9 100644 --- a/seahub/templates/common_file_view_react.html +++ b/seahub/templates/common_file_view_react.html @@ -18,6 +18,8 @@ previousImage: {% if img_prev %}'{{ img_prev|escapejs }}'{% else %}false{% endif nextImage: {% if img_next %}'{{ img_next|escapejs }}'{% else %}false{% endif %}, fileExt: '{{ fileext|escapejs }}', thumbnailSizeForOriginal: {{ thumbnail_size_for_original }}, +thumbnailSizeForGrid: {{ thumbnail_size_for_grid }}, +thumbnailDefaultSize: {{ thumbnail_default_size }}, {% endif %} {% if filetype == 'Video' %} diff --git a/tests/api/endpoints/test_dir_view.py b/tests/api/endpoints/test_dir_view.py index ef88cc82a1..eee79904bc 100644 --- a/tests/api/endpoints/test_dir_view.py +++ b/tests/api/endpoints/test_dir_view.py @@ -11,7 +11,7 @@ from seahub.test_utils import BaseTestCase from seahub.utils import check_filename_with_rename from tests.common.utils import randstring -from seahub.settings import THUMBNAIL_ROOT +from seahub.settings import THUMBNAIL_ROOT, THUMBNAIL_DEFAULT_SIZE try: from seahub.settings import LOCAL_PRO_DEV_ENV @@ -266,8 +266,7 @@ class DirViewTest(BaseTestCase): file_id = json_resp['dirent_list'][0]['id'] # prepare thumbnail - size = 48 - thumbnail_dir = os.path.join(THUMBNAIL_ROOT, str(size)) + thumbnail_dir = os.path.join(THUMBNAIL_ROOT, str(THUMBNAIL_DEFAULT_SIZE)) if not os.path.exists(thumbnail_dir): os.makedirs(thumbnail_dir) thumbnail_file = os.path.join(thumbnail_dir, file_id)