Merge pull request #600 from ONLYOFFICE/bugfix/tile-rerender

Client: Fixed re-render tile
This commit is contained in:
Alexey Safronov 2024-08-23 15:34:49 +04:00 committed by GitHub
commit b083009309
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 149 additions and 96 deletions

View File

@ -73,6 +73,7 @@
"@babel/preset-react": "^7.18.6", "@babel/preset-react": "^7.18.6",
"@babel/preset-typescript": "^7.21.0", "@babel/preset-typescript": "^7.21.0",
"@svgr/webpack": "^5.5.0", "@svgr/webpack": "^5.5.0",
"@types/element-resize-detector": "^1.1.6",
"@types/eslint": "^8.44.7", "@types/eslint": "^8.44.7",
"@types/he": "^1.2.3", "@types/he": "^1.2.3",
"@typescript-eslint/eslint-plugin": "^6.12.0", "@typescript-eslint/eslint-plugin": "^6.12.0",

View File

@ -23,10 +23,12 @@
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing // All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0 // content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode // International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
import { useContext } from "react";
import { observer, inject } from "mobx-react"; import { observer, inject } from "mobx-react";
//import { useLocation } from "react-router-dom"; //import { useLocation } from "react-router-dom";
import { Context } from "@docspace/shared/utils";
import { Events, FileExtensions } from "@docspace/shared/enums"; import { Events, FileExtensions } from "@docspace/shared/enums";
import RootFolderContainer from "./RootFolderContainer"; import RootFolderContainer from "./RootFolderContainer";
@ -49,7 +51,6 @@ const EmptyContainer = ({
theme, theme,
type, type,
sectionWidth,
isRoomNotFoundOrMoved, isRoomNotFoundOrMoved,
isGracePeriod, isGracePeriod,
setQuotaWarningDialogVisible, setQuotaWarningDialogVisible,
@ -60,6 +61,8 @@ const EmptyContainer = ({
}) => { }) => {
//const location = useLocation(); //const location = useLocation();
const { sectionWidth } = useContext(Context);
linkStyles.color = theme.filesEmptyContainer.linkColor; linkStyles.color = theme.filesEmptyContainer.linkColor;
const onCreate = (e) => { const onCreate = (e) => {

View File

@ -25,12 +25,13 @@
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode // International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
import styled from "styled-components"; import styled from "styled-components";
import { useMemo } from "react"; import { useMemo, useContext } from "react";
import { inject, observer } from "mobx-react"; import { inject, observer } from "mobx-react";
import useViewEffect from "SRC_DIR/Hooks/useViewEffect"; import useViewEffect from "SRC_DIR/Hooks/useViewEffect";
import { Base } from "@docspace/shared/themes"; import { Base } from "@docspace/shared/themes";
import { Context } from "@docspace/shared/utils";
import { RowContainer } from "@docspace/shared/components/row-container"; import { RowContainer } from "@docspace/shared/components/row-container";
import SimpleFilesRow from "./SimpleFilesRow"; import SimpleFilesRow from "./SimpleFilesRow";
@ -62,7 +63,6 @@ StyledRowContainer.defaultProps = { theme: Base };
const FilesRowContainer = ({ const FilesRowContainer = ({
filesList, filesList,
sectionWidth,
viewAs, viewAs,
setViewAs, setViewAs,
infoPanelVisible, infoPanelVisible,
@ -75,6 +75,8 @@ const FilesRowContainer = ({
highlightFile, highlightFile,
currentDeviceType, currentDeviceType,
}) => { }) => {
const { sectionWidth } = useContext(Context);
useViewEffect({ useViewEffect({
view: viewAs, view: viewAs,
setView: setViewAs, setView: setViewAs,

View File

@ -28,13 +28,20 @@ import { inject, observer } from "mobx-react";
import styled, { css } from "styled-components"; import styled, { css } from "styled-components";
import { useNavigate, useLocation } from "react-router-dom"; import { useNavigate, useLocation } from "react-router-dom";
import elementResizeDetectorMaker from "element-resize-detector"; import elementResizeDetectorMaker from "element-resize-detector";
import React, { useEffect, useRef, useCallback, useMemo } from "react"; import React, {
useEffect,
useRef,
useCallback,
useMemo,
useContext,
} from "react";
import useViewEffect from "SRC_DIR/Hooks/useViewEffect"; import useViewEffect from "SRC_DIR/Hooks/useViewEffect";
import { Base } from "@docspace/shared/themes"; import { Base } from "@docspace/shared/themes";
import { TableContainer } from "@docspace/shared/components/table"; import { TableContainer } from "@docspace/shared/components/table";
import { TableBody } from "@docspace/shared/components/table"; import { TableBody } from "@docspace/shared/components/table";
import { Context } from "@docspace/shared/utils";
import TableRow from "./TableRow"; import TableRow from "./TableRow";
import TableHeader from "./TableHeader"; import TableHeader from "./TableHeader";
@ -121,7 +128,6 @@ const elementResizeDetector = elementResizeDetectorMaker({
const Table = ({ const Table = ({
filesList, filesList,
sectionWidth,
viewAs, viewAs,
setViewAs, setViewAs,
setFirsElemChecked, setFirsElemChecked,
@ -142,6 +148,8 @@ const Table = ({
const [tagCount, setTagCount] = React.useState(null); const [tagCount, setTagCount] = React.useState(null);
const [hideColumns, setHideColumns] = React.useState(false); const [hideColumns, setHideColumns] = React.useState(false);
const { sectionWidth } = useContext(Context);
const ref = useRef(null); const ref = useRef(null);
const tagRef = useRef(null); const tagRef = useRef(null);

View File

@ -24,14 +24,17 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0 // content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode // International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
import React, { useEffect } from "react"; import React, { useEffect, useContext } from "react";
import styled from "styled-components"; import styled from "styled-components";
import { inject, observer } from "mobx-react"; import { inject, observer } from "mobx-react";
import { withTranslation } from "react-i18next"; import { withTranslation } from "react-i18next";
import DragAndDrop from "@docspace/shared/components/drag-and-drop/DragAndDrop"; import DragAndDrop from "@docspace/shared/components/drag-and-drop/DragAndDrop";
// import { Context } from "@docspace/shared/utils";
import Tile from "./sub-components/Tile"; import Tile from "./sub-components/Tile";
import FilesTileContent from "./FilesTileContent"; import FilesTileContent from "./FilesTileContent";
import { FileTileContext } from "./FileTile.provider";
import withFileActions from "../../../../../HOCs/withFileActions"; import withFileActions from "../../../../../HOCs/withFileActions";
import withQuickButtons from "../../../../../HOCs/withQuickButtons"; import withQuickButtons from "../../../../../HOCs/withQuickButtons";
@ -45,7 +48,6 @@ const StyledDragAndDrop = styled(DragAndDrop)`
const FileTile = (props) => { const FileTile = (props) => {
const { const {
item, item,
sectionWidth,
dragging, dragging,
onContentFileSelect, onContentFileSelect,
fileContextClick, fileContextClick,
@ -70,12 +72,12 @@ const FileTile = (props) => {
t, t,
getContextModel, getContextModel,
onHideContextMenu, onHideContextMenu,
thumbSize, // thumbSize,
setSelection, setSelection,
id, id,
onSelectTag, onSelectTag,
onSelectOption, onSelectOption,
columnCount, // columnCount,
isRooms, isRooms,
withCtrlSelect, withCtrlSelect,
withShiftSelect, withShiftSelect,
@ -86,6 +88,10 @@ const FileTile = (props) => {
badgeUrl, badgeUrl,
} = props; } = props;
// const { sectionWidth } = useContext(Context);
const { columnCount, thumbSize } = useContext(FileTileContext);
const temporaryExtension = const temporaryExtension =
item.id === -1 ? `.${item.fileExst}` : item.fileExst; item.id === -1 ? `.${item.fileExst}` : item.fileExst;
@ -145,7 +151,7 @@ const FileTile = (props) => {
: thumbnailUrl : thumbnailUrl
} }
element={element} element={element}
sectionWidth={sectionWidth} // sectionWidth={sectionWidth}
contentElement={quickButtonsComponent} contentElement={quickButtonsComponent}
onSelect={onContentFileSelect} onSelect={onContentFileSelect}
tileContextClick={fileContextClick} tileContextClick={fileContextClick}
@ -177,7 +183,7 @@ const FileTile = (props) => {
> >
<FilesTileContent <FilesTileContent
item={item} item={item}
sectionWidth={sectionWidth} // sectionWidth={sectionWidth}
onFilesClick={onFilesClick} onFilesClick={onFilesClick}
/> />
{badgesComponent} {badgesComponent}

View File

@ -0,0 +1,28 @@
import { createContext, PropsWithChildren, useMemo } from "react";
type FileTileContextType = {
thumbSize: string;
columnCount: null | number;
};
export const FileTileContext = createContext<FileTileContextType>({
columnCount: null,
thumbSize: "",
});
export const FileTileProvider = ({
children,
columnCount,
thumbSize,
}: PropsWithChildren<FileTileContextType>) => {
const value = useMemo(
() => ({ columnCount, thumbSize }),
[thumbSize, columnCount],
);
return (
<FileTileContext.Provider value={value}>
{children}
</FileTileContext.Provider>
);
};

View File

@ -0,0 +1,30 @@
import elementResizeDetectorMaker from "element-resize-detector";
export const getThumbSize = (width: number): string => {
let imgWidth = 216;
if (width >= 240 && width < 264) {
imgWidth = 240;
} else if (width >= 264 && width < 288) {
imgWidth = 264;
} else if (width >= 288 && width < 312) {
imgWidth = 288;
} else if (width >= 312 && width < 336) {
imgWidth = 312;
} else if (width >= 336 && width < 360) {
imgWidth = 336;
} else if (width >= 360 && width < 400) {
imgWidth = 360;
} else if (width >= 400 && width < 440) {
imgWidth = 400;
} else if (width >= 440) {
imgWidth = 440;
}
return `${imgWidth}x156`;
};
export const elementResizeDetector = elementResizeDetectorMaker({
strategy: "scroll",
callOnAdd: false,
});

View File

@ -30,45 +30,21 @@ import React, {
useCallback, useCallback,
useState, useState,
useMemo, useMemo,
useContext,
} from "react"; } from "react";
import { inject, observer } from "mobx-react"; import { inject, observer } from "mobx-react";
import elementResizeDetectorMaker from "element-resize-detector";
import TileContainer from "./sub-components/TileContainer"; import { Context } from "@docspace/shared/utils";
import FileTile from "./FileTile"; import FileTile from "./FileTile";
import { FileTileProvider } from "./FileTile.provider";
import { elementResizeDetector, getThumbSize } from "./FileTile.utils";
const getThumbSize = (width) => { import TileContainer from "./sub-components/TileContainer";
let imgWidth = 216;
if (width >= 240 && width < 264) {
imgWidth = 240;
} else if (width >= 264 && width < 288) {
imgWidth = 264;
} else if (width >= 288 && width < 312) {
imgWidth = 288;
} else if (width >= 312 && width < 336) {
imgWidth = 312;
} else if (width >= 336 && width < 360) {
imgWidth = 336;
} else if (width >= 360 && width < 400) {
imgWidth = 360;
} else if (width >= 400 && width < 440) {
imgWidth = 400;
} else if (width >= 440) {
imgWidth = 440;
}
return `${imgWidth}x156`;
};
const elementResizeDetector = elementResizeDetectorMaker({
strategy: "scroll",
callOnAdd: false,
});
const FilesTileContainer = ({ const FilesTileContainer = ({
filesList, filesList,
t, t,
sectionWidth,
withPaging, withPaging,
thumbnails1280x720, thumbnails1280x720,
}) => { }) => {
@ -78,6 +54,8 @@ const FilesTileContainer = ({
const [thumbSize, setThumbSize] = useState(""); const [thumbSize, setThumbSize] = useState("");
const [columnCount, setColumnCount] = useState(null); const [columnCount, setColumnCount] = useState(null);
const { sectionWidth } = useContext(Context);
useEffect(() => { useEffect(() => {
return () => { return () => {
isMountedRef.current = false; isMountedRef.current = false;
@ -139,10 +117,7 @@ const FilesTileContainer = ({
} }
item={item} item={item}
itemIndex={index} itemIndex={index}
sectionWidth={sectionWidth}
selectableRef={onSetTileRef} selectableRef={onSetTileRef}
thumbSize={thumbSize}
columnCount={columnCount}
withRef={true} withRef={true}
/> />
) : ( ) : (
@ -153,15 +128,13 @@ const FilesTileContainer = ({
} }
item={item} item={item}
itemIndex={index} itemIndex={index}
sectionWidth={sectionWidth}
thumbSize={thumbSize}
columnCount={columnCount}
/> />
); );
}); });
}, [filesList, sectionWidth, onSetTileRef, thumbSize, columnCount]); }, [filesList, onSetTileRef, sectionWidth]);
return ( return (
<FileTileProvider columnCount={columnCount} thumbSize={thumbSize}>
<TileContainer <TileContainer
className="tile-container" className="tile-container"
draggable draggable
@ -171,6 +144,7 @@ const FilesTileContainer = ({
> >
{filesListNode} {filesListNode}
</TileContainer> </TileContainer>
</FileTileProvider>
); );
}; };

View File

@ -26,9 +26,8 @@
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import { withTranslation } from "react-i18next"; import { withTranslation } from "react-i18next";
import { useLocation } from "react-router-dom";
import { observer, inject } from "mobx-react"; import { observer, inject } from "mobx-react";
import FilesRowContainer from "./RowsView/FilesRowContainer"; import FilesRowContainer from "./RowsView/FilesRowContainer";
import FilesTileContainer from "./TilesView/FilesTileContainer"; import FilesTileContainer from "./TilesView/FilesTileContainer";
import EmptyContainer from "../../../../components/EmptyContainer"; import EmptyContainer from "../../../../components/EmptyContainer";
@ -37,7 +36,6 @@ import TableView from "./TableView/TableContainer";
import withHotkeys from "../../../../HOCs/withHotkeys"; import withHotkeys from "../../../../HOCs/withHotkeys";
import { import {
clearEdgeScrollingTimer, clearEdgeScrollingTimer,
Consumer,
isMobile, isMobile,
isTablet, isTablet,
onEdgeScrolling, onEdgeScrolling,
@ -307,36 +305,18 @@ const SectionBodyContent = (props) => {
if (isEmptyFilesList && movingInProgress) return <></>; if (isEmptyFilesList && movingInProgress) return <></>;
const showEmptyPage = isEmptyFilesList; if (isEmptyFilesList) return <EmptyContainer isEmptyPage={isEmptyPage} />;
return ( return (
<Consumer>
{(context) =>
showEmptyPage ? (
<> <>
<EmptyContainer {viewAs === "tile" ? (
sectionWidth={context.sectionWidth} <FilesTileContainer t={t} />
isEmptyPage={isEmptyPage}
/>
</>
) : viewAs === "tile" ? (
<>
<FilesTileContainer sectionWidth={context.sectionWidth} t={t} />
</>
) : viewAs === "table" ? ( ) : viewAs === "table" ? (
<> <TableView tReady={tReady} />
<TableView sectionWidth={context.sectionWidth} tReady={tReady} />
</>
) : ( ) : (
<> <FilesRowContainer tReady={tReady} />
<FilesRowContainer )}
sectionWidth={context.sectionWidth}
tReady={tReady}
/>
</> </>
)
}
</Consumer>
); );
}; };

View File

@ -25,7 +25,7 @@
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode // International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
/* eslint-disable @typescript-eslint/no-unused-vars */ /* eslint-disable @typescript-eslint/no-unused-vars */
import React from "react"; import React, { useEffect, useMemo } from "react";
import { Provider } from "../../utils"; import { Provider } from "../../utils";
import { DeviceType } from "../../enums"; import { DeviceType } from "../../enums";
@ -153,6 +153,16 @@ const Section = (props: SectionProps) => {
isSectionBodyAvailable || isSectionBodyAvailable ||
isSectionPagingAvailable; isSectionPagingAvailable;
useEffect(() => {
if (!containerRef.current) return;
const computedStyles = window.getComputedStyle(containerRef.current, null);
const width = +computedStyles.getPropertyValue("width").replace("px", "");
const height = +computedStyles.getPropertyValue("height").replace("px", "");
setSectionSize(() => ({ width, height }));
}, [isInfoPanelVisible]);
const onResize = React.useCallback(() => { const onResize = React.useCallback(() => {
if (timerRef.current) clearTimeout(timerRef.current); if (timerRef.current) clearTimeout(timerRef.current);
@ -188,14 +198,17 @@ const Section = (props: SectionProps) => {
const showTwoProgress = showPrimaryProgressBar && showSecondaryProgressBar; const showTwoProgress = showPrimaryProgressBar && showSecondaryProgressBar;
return ( const providerValue = useMemo(
isSectionAvailable && ( () => ({
<Provider
value={{
sectionWidth: sectionSize.width, sectionWidth: sectionSize.width,
sectionHeight: sectionSize.height, sectionHeight: sectionSize.height,
}} }),
> [sectionSize.width, sectionSize.height],
);
return (
isSectionAvailable && (
<Provider value={providerValue}>
<SectionContainer <SectionContainer
viewAs={viewAs} viewAs={viewAs}
ref={containerRef} ref={containerRef}

View File

@ -2580,6 +2580,7 @@ __metadata:
"@babel/preset-typescript": "npm:^7.21.0" "@babel/preset-typescript": "npm:^7.21.0"
"@codemirror/lang-javascript": "npm:^6.2.2" "@codemirror/lang-javascript": "npm:^6.2.2"
"@svgr/webpack": "npm:^5.5.0" "@svgr/webpack": "npm:^5.5.0"
"@types/element-resize-detector": "npm:^1.1.6"
"@types/eslint": "npm:^8.44.7" "@types/eslint": "npm:^8.44.7"
"@types/he": "npm:^1.2.3" "@types/he": "npm:^1.2.3"
"@typescript-eslint/eslint-plugin": "npm:^6.12.0" "@typescript-eslint/eslint-plugin": "npm:^6.12.0"
@ -7627,6 +7628,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@types/element-resize-detector@npm:^1.1.6":
version: 1.1.6
resolution: "@types/element-resize-detector@npm:1.1.6"
checksum: 10/62967c4933ce6dc717608aa498bfbbf2567c3778958203621b1981f5804eb519cf16b8f677d3c92c9b2a9d791191b514dd60298e276fcbf6b1660542209dd299
languageName: node
linkType: hard
"@types/emscripten@npm:^1.39.6": "@types/emscripten@npm:^1.39.6":
version: 1.39.10 version: 1.39.10
resolution: "@types/emscripten@npm:1.39.10" resolution: "@types/emscripten@npm:1.39.10"