diff --git a/frontend/src/components/dir-view-mode/constants.js b/frontend/src/components/dir-view-mode/constants.js index 0f0485ca85..6e27ee40ae 100644 --- a/frontend/src/components/dir-view-mode/constants.js +++ b/frontend/src/components/dir-view-mode/constants.js @@ -1,3 +1,4 @@ +export * from '../../metadata/constants'; export const LIST_MODE = 'list'; export const GRID_MODE = 'grid'; export const METADATA_MODE = 'metadata'; diff --git a/frontend/src/components/dirent-detail/detail-container.js b/frontend/src/components/dirent-detail/detail-container.js index 5eb994c7c8..d442a8093f 100644 --- a/frontend/src/components/dirent-detail/detail-container.js +++ b/frontend/src/components/dirent-detail/detail-container.js @@ -1,38 +1,51 @@ -import React from 'react'; +import React, { useEffect } from 'react'; import PropTypes from 'prop-types'; import LibDetail from './lib-details'; import DirentDetail from './dirent-details'; import GalleryDetail from '../../metadata/components/gallery-details'; import ObjectUtils from '../../metadata/utils/object-utils'; +import { MetadataContext } from '../../metadata'; import { METADATA_MODE } from '../dir-view-mode/constants'; const DetailContainer = React.memo(({ repoID, path, dirent, currentRepoInfo, repoTags, fileTags, onClose, onFileTagChanged, mode }) => { - const renderContent = () => { - if (mode === METADATA_MODE) { - const viewID = path.split('/').pop(); - return ; + useEffect(() => { + // init context + if (!window.sfMetadataContext) { + const context = new MetadataContext(); + window.sfMetadataContext = context; + window.sfMetadataContext.init({ repoID, repoInfo: currentRepoInfo }); } - if (path === '/' && !dirent) { - return ; - } + return () => { + if (window.sfMetadataContext && mode !== METADATA_MODE) { + window.sfMetadataContext.destroy(); + delete window['sfMetadataContext']; + } + }; + }, [repoID, currentRepoInfo, mode]); + + if (mode === METADATA_MODE) { + const viewID = path.split('/').pop(); + return ; + } + + if (path === '/' && !dirent) { + return ; + } - return ( - - ); - }; - - return renderContent(); + return ( + + ); }, (props, nextProps) => { const isChanged = props.repoID !== nextProps.repoID || diff --git a/frontend/src/metadata/components/gallery-details/index.js b/frontend/src/metadata/components/gallery-details/index.js index c3281834bf..323155b797 100644 --- a/frontend/src/metadata/components/gallery-details/index.js +++ b/frontend/src/metadata/components/gallery-details/index.js @@ -9,7 +9,7 @@ import { Utils } from '../../../utils/utils'; import { gettext, siteRoot, thumbnailSizeForGrid } from '../../../utils/constants'; import { Detail, Header, Body } from '../../../components/dirent-detail/detail'; import { CellType, PRIVATE_COLUMN_KEY } from '../../constants'; -import { useMetadata } from '../../../metadata'; +import { useMetadata, useGallery } from '../../../metadata'; import { seafileAPI } from '../../../utils/seafile-api'; import FileDetails from '../../../components/dirent-detail/dirent-details/file-details'; import { Dirent } from '../../../models'; @@ -18,39 +18,14 @@ const GalleryDetail = ({ currentRepoInfo, viewID, onClose }) => { const [isLoading, setLoading] = useState(true); const [repo, setRepo] = useState({}); const [direntDetail, setDirentDetail] = useState(null); - const { viewsMap, currentImage } = useMetadata(); + const { viewsMap } = useMetadata(); + const { currentImage } = useGallery(); const view = useMemo(() => viewsMap[viewID], [viewID, viewsMap]); const icon = useMemo(() => Utils.getFolderIconUrl(), []); - const filesField = useMemo(() => ({ type: CellType.NUMBER, name: gettext('Files') }), []); - const sizeField = useMemo(() => ({ type: CellType.TEXT, name: gettext('Size') }), []); const creatorField = useMemo(() => ({ type: CellType.CREATOR, name: gettext('Creator') }), []); const mtimeField = useMemo(() => ({ type: CellType.MTIME, name: gettext('Last modified time') }), []); - const filesCount = useMemo(() => { - if (!window.sfMetadataContext || !window.sfMetadataStore) return 0; - - const store = window.sfMetadataStore; - return store.data.rows.reduce((count, row) => Utils.imageCheck(row[PRIVATE_COLUMN_KEY.FILE_NAME]) ? count + 1 : count, 0); - }, []); - - const sizeCount = useMemo(() => { - // count all images size - if (!window.sfMetadataContext || !window.sfMetadataStore) return 0; - - const store = window.sfMetadataStore; - const total = store.data.rows.reduce((size, row) => { - if (Utils.imageCheck(row[PRIVATE_COLUMN_KEY.FILE_NAME])) { - const sizeStr = row[PRIVATE_COLUMN_KEY.SIZE]; - const sizeNum = parseInt(sizeStr); - return size + sizeNum; - } - return size; - }, 0); - - return Utils.bytesToSize(total); - }, []); - useEffect(() => { setLoading(true); seafileAPI.getRepoInfo(currentRepoInfo.repo_id).then(res => { @@ -101,18 +76,9 @@ const GalleryDetail = ({ currentRepoInfo, viewID, onClose }) => {
) : (
- - - - - - - - - { + const [currentImage, setCurrentImage] = useState(null); + + const updateCurrentImage = useCallback((image) => { + setCurrentImage(image); + }, []); + + return ( + + {children} + + ); +}; + +export const useGallery = () => { + const context = useContext(GalleryContext); + + if (!context) { + throw new Error('\'GalleryContext\' is null'); + } + + return context; +}; diff --git a/frontend/src/metadata/hooks/index.js b/frontend/src/metadata/hooks/index.js index 74b4c9ab56..73beeb7a5a 100644 --- a/frontend/src/metadata/hooks/index.js +++ b/frontend/src/metadata/hooks/index.js @@ -1,3 +1,4 @@ export { MetadataProvider, useMetadata } from './metadata'; export { EnableMetadataProvider, useEnableMetadata } from './enable-metadata'; export { CollaboratorsProvider, useCollaborators } from './collaborators'; +export { GalleryProvider, useGallery } from './gallery'; diff --git a/frontend/src/metadata/hooks/metadata.js b/frontend/src/metadata/hooks/metadata.js index 0476fb6f62..ce634afc75 100644 --- a/frontend/src/metadata/hooks/metadata.js +++ b/frontend/src/metadata/hooks/metadata.js @@ -20,7 +20,6 @@ export const MetadataProvider = ({ repoID, hideMetadataView, selectMetadataView, const [navigation, setNavigation] = useState([]); const [staticView, setStaticView] = useState([]); const [, setCount] = useState(0); - const [currentImage, setCurrentImage] = useState(null); const viewsMap = useRef({}); @@ -139,6 +138,7 @@ export const MetadataProvider = ({ repoID, hideMetadataView, selectMetadataView, name: isFaceRecognitionView ? gettext('Photos - classfied by people') : gettext('File extended properties'), type: isFaceRecognitionView ? PRIVATE_FILE_TYPE.FACE_RECOGNITION : PRIVATE_FILE_TYPE.FILE_EXTENDED_PROPERTIES, isDir: () => false, + viewType: view.type, }, parentNode: {}, key: repoID, @@ -214,10 +214,6 @@ export const MetadataProvider = ({ repoID, hideMetadataView, selectMetadataView, }); }, [repoID]); - const updateCurrentImage = useCallback((image) => { - setCurrentImage(image); - }, []); - return ( {children} diff --git a/frontend/src/metadata/views/gallery/gallery-main.js b/frontend/src/metadata/views/gallery/gallery-main.js index 74b57c45b8..82a77b5907 100644 --- a/frontend/src/metadata/views/gallery/gallery-main.js +++ b/frontend/src/metadata/views/gallery/gallery-main.js @@ -81,7 +81,16 @@ const GalleryMain = ({ }, []); const handleClickOutside = useCallback((e) => { - if (imageRef.current && !imageRef.current.contains(e.target) && containerRef.current && containerRef.current.contains(e.target)) { + const images = containerRef.current.querySelectorAll('.metadata-gallery-image-item'); + let isClickInsideImage = false; + + images.forEach(img => { + if (img.contains(e.target)) { + isClickInsideImage = true; + } + }); + + if (!isClickInsideImage && containerRef.current.contains(e.target)) { onImageSelect([]); } }, [onImageSelect]); @@ -129,7 +138,6 @@ const GalleryMain = ({
{name || gettext('Empty')}
)}
{ const containerRef = useRef(null); const renderMoreTimer = useRef(null); - const { updateCurrentImage } = useMetadata(); + const { updateCurrentImage } = useGallery(); const { metadata, store } = useMetadataView(); const repoID = store.repoId; - useEffect(() => { - updateCurrentImage(selectedImages[0]); - }, [selectedImages, updateCurrentImage]); + useEffect(() => updateCurrentImage(selectedImages[0]), [selectedImages, updateCurrentImage]); const selectedImageIDs = useMemo(() => { return selectedImages.map(image => image.id); 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 2516ddf7b7..1a871643ce 100644 --- a/frontend/src/pages/lib-content-view/lib-content-view.js +++ b/frontend/src/pages/lib-content-view/lib-content-view.js @@ -21,8 +21,8 @@ import CopyMoveDirentProgressDialog from '../../components/dialog/copy-move-dire import DeleteFolderDialog from '../../components/dialog/delete-folder-dialog'; import { EVENT_BUS_TYPE } from '../../components/common/event-bus-type'; import { PRIVATE_FILE_TYPE } from '../../constants'; -import { MetadataProvider, CollaboratorsProvider } from '../../metadata/hooks'; -import { LIST_MODE, METADATA_MODE, FACE_RECOGNITION_MODE } from '../../components/dir-view-mode/constants'; +import { MetadataProvider, CollaboratorsProvider, GalleryProvider } from '../../metadata/hooks'; +import { LIST_MODE, METADATA_MODE, FACE_RECOGNITION_MODE, VIEW_TYPE } from '../../components/dir-view-mode/constants'; import CurDirPath from '../../components/cur-dir-path'; import DirTool from '../../components/cur-dir-path/dir-tool'; import DetailContainer from '../../components/dirent-detail/detail-container'; @@ -538,14 +538,14 @@ class LibContentView extends React.Component { window.history.pushState({ url: url, path: filePath }, filePath, url); }; - showFileMetadata = (filePath, viewId) => { + showFileMetadata = (filePath, viewId, viewType) => { const repoID = this.props.repoID; const repoInfo = this.state.currentRepoInfo; this.setState({ currentMode: METADATA_MODE, path: filePath, viewId: viewId, - isDirentDetailShow: false + isDirentDetailShow: viewType === VIEW_TYPE.GALLERY ? this.state.isDirentDetailShow : false, }, () => { setTimeout(() => { this.unsubscribeEventBus = window.sfMetadataContext.eventBus.subscribe(EVENT_BUS_TYPE.OPEN_MARKDOWN_DIALOG, this.openMarkDownDialog); @@ -1897,7 +1897,7 @@ class LibContentView extends React.Component { } } else if (Utils.isFileMetadata(node?.object?.type)) { if (node.path !== this.state.path) { - this.showFileMetadata(node.path, node.view_id || '0000'); + this.showFileMetadata(node.path, node.view_id || '0000', node.object.viewType); } } else if (Utils.isFaceRecognition(node?.object?.type)) { if (node.path !== this.state.path) { @@ -2360,92 +2360,94 @@ class LibContentView extends React.Component {
}
-
- {this.state.pathExist ? - - : -
{gettext('Folder does not exist.')}
- } - {this.state.isDirentDetailShow && ( - - )} -
+ +
+ {this.state.pathExist ? + + : +
{gettext('Folder does not exist.')}
+ } + {this.state.isDirentDetailShow && ( + + )} +
+
{canUpload && this.state.pathExist && !this.state.isViewFile && this.state.currentMode !== METADATA_MODE && (