From 0ddcfd8b62bd4115338371daefe636fd6f12eb8d Mon Sep 17 00:00:00 2001 From: gopienkonikita Date: Tue, 6 Aug 2024 14:34:33 +0300 Subject: [PATCH 1/2] Web: Components: InfiniteLoader: added skeleton when quickly scrolling the list, added skeleton for room tiles --- .../TilesView/sub-components/InfiniteGrid.js | 1 + .../infinite-loader/InfiniteLoader.styled.ts | 43 +++++++++- .../infinite-loader/InfiniteLoader.tsx | 45 +++++++++- .../infinite-loader/InfiniteLoader.types.ts | 1 + .../infinite-loader/sub-components/Grid.tsx | 46 +++++++++- .../infinite-loader/sub-components/List.tsx | 11 ++- packages/shared/skeletons/tiles/Tile.tsx | 83 ++++++++++++++++++- .../shared/skeletons/tiles/Tiles.styled.ts | 23 +++++ .../shared/skeletons/tiles/Tiles.types.ts | 1 + packages/shared/utils/device.ts | 1 + 10 files changed, 245 insertions(+), 10 deletions(-) diff --git a/packages/client/src/pages/Home/Section/Body/TilesView/sub-components/InfiniteGrid.js b/packages/client/src/pages/Home/Section/Body/TilesView/sub-components/InfiniteGrid.js index f3104c9907..625170db8e 100644 --- a/packages/client/src/pages/Home/Section/Body/TilesView/sub-components/InfiniteGrid.js +++ b/packages/client/src/pages/Home/Section/Body/TilesView/sub-components/InfiniteGrid.js @@ -196,6 +196,7 @@ const InfiniteGrid = (props) => { key={key} className={`tiles-loader ${type}`} isFolder={type === "isFolder"} + isRoom={type === "isRoom"} />, ); } diff --git a/packages/shared/components/infinite-loader/InfiniteLoader.styled.ts b/packages/shared/components/infinite-loader/InfiniteLoader.styled.ts index 0fe163a976..e297c56f4f 100644 --- a/packages/shared/components/infinite-loader/InfiniteLoader.styled.ts +++ b/packages/shared/components/infinite-loader/InfiniteLoader.styled.ts @@ -28,7 +28,7 @@ import { List } from "react-virtualized"; import styled, { css } from "styled-components"; import { Base } from "../../themes"; -import { mobile, tablet } from "../../utils"; +import { desktop, mobile, tablet } from "../../utils"; import { TViewAs } from "../../types"; const StyledScroll = styled.div` @@ -157,4 +157,43 @@ StyledScroll.defaultProps = { theme: Base, }; -export { StyledScroll, StyledList }; +const paddingCss = css` + @media ${desktop} { + ${(props) => + props.theme.interfaceDirection === "rtl" + ? css` + margin-right: 1px; + padding-left: 0px; + ` + : css` + margin-left: 1px; + padding-right: 0px; + `} + } + + @media ${tablet} { + ${(props) => + props.theme.interfaceDirection === "rtl" + ? css` + margin-right: -1px; + ` + : css` + margin-left: -1px; + `} + } +`; + +const StyledItem = styled.div` + display: grid; + grid-template-columns: repeat(auto-fill, minmax(216px, 1fr)); + gap: 14px 16px; + width: 100%; + + @media ${tablet} { + gap: 14px; + } + + ${paddingCss}; +`; + +export { StyledScroll, StyledList, StyledItem }; diff --git a/packages/shared/components/infinite-loader/InfiniteLoader.tsx b/packages/shared/components/infinite-loader/InfiniteLoader.tsx index bae74b22fe..85708e28f5 100644 --- a/packages/shared/components/infinite-loader/InfiniteLoader.tsx +++ b/packages/shared/components/infinite-loader/InfiniteLoader.tsx @@ -24,27 +24,66 @@ // 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 -import React from "react"; +import { useState, useEffect } from "react"; import { isMobile } from "../../utils"; import ListComponent from "./sub-components/List"; import GridComponent from "./sub-components/Grid"; import { InfiniteLoaderProps } from "./InfiniteLoader.types"; +import { MAX_INFINITE_LOADER_SHIFT } from "../../utils/device"; const InfiniteLoaderComponent = (props: InfiniteLoaderProps) => { const { viewAs, isLoading } = props; + const [scrollTop, setScrollTop] = useState(0); + const [showSkeleton, setShowSkeleton] = useState(false); + const scroll = isMobile() ? document.querySelector("#customScrollBar .scroll-wrapper > .scroller") : document.querySelector("#sectionScroll .scroll-wrapper > .scroller"); + const onScroll = (e: Event) => { + const eventTarget = e.target as HTMLElement; + const currentScrollTop = eventTarget.scrollTop; + + setScrollTop(currentScrollTop ?? 0); + + const scrollShift = scrollTop - currentScrollTop; + + if ( + scrollShift > MAX_INFINITE_LOADER_SHIFT || + scrollShift < -MAX_INFINITE_LOADER_SHIFT + ) { + setShowSkeleton(true); + setTimeout(() => { + setShowSkeleton(false); + }, 200); + } + }; + + useEffect(() => { + if (scroll) scroll.addEventListener("scroll", onScroll); + + return () => { + if (scroll) scroll.removeEventListener("scroll", onScroll); + }; + }); + if (isLoading) return null; return viewAs === "tile" ? ( - + ) : ( - + ); }; diff --git a/packages/shared/components/infinite-loader/InfiniteLoader.types.ts b/packages/shared/components/infinite-loader/InfiniteLoader.types.ts index d1203bddf7..673cbff85d 100644 --- a/packages/shared/components/infinite-loader/InfiniteLoader.types.ts +++ b/packages/shared/components/infinite-loader/InfiniteLoader.types.ts @@ -42,6 +42,7 @@ export interface InfiniteLoaderProps { className?: string; infoPanelVisible?: boolean; countTilesInRow?: number; + showSkeleton?: boolean; } export interface ListComponentProps extends InfiniteLoaderProps { diff --git a/packages/shared/components/infinite-loader/sub-components/Grid.tsx b/packages/shared/components/infinite-loader/sub-components/Grid.tsx index 5d50bfa67f..6b872a04e3 100644 --- a/packages/shared/components/infinite-loader/sub-components/Grid.tsx +++ b/packages/shared/components/infinite-loader/sub-components/Grid.tsx @@ -26,8 +26,10 @@ import React, { useCallback, useEffect, useRef } from "react"; import { InfiniteLoader, WindowScroller, List } from "react-virtualized"; -import { StyledList } from "../InfiniteLoader.styled"; +import { StyledItem, StyledList } from "../InfiniteLoader.styled"; import { GridComponentProps } from "../InfiniteLoader.types"; +import { TileSkeleton } from "../../../skeletons/tiles"; +import { RectangleSkeleton } from "../../../skeletons"; const GridComponent = ({ hasMoreFiles, @@ -39,12 +41,13 @@ const GridComponent = ({ children, className, scroll, + showSkeleton, }: GridComponentProps) => { const loaderRef = useRef(null); const listRef = useRef(null); useEffect(() => { - listRef?.current?.recomputeRowHeights(); + // listRef?.current?.recomputeRowHeights(); //TODO: return there will be problems with the height of the tile when clicking on the backspace }); const isItemLoaded = useCallback( @@ -58,11 +61,50 @@ const GridComponent = ({ index, style, key, + isScrolling, }: { index: number; style: React.CSSProperties; key: string; + isScrolling: boolean; }) => { + const elem = children[index] as React.ReactElement; + const itemClassNames = elem.props?.className; + + const isFolder = itemClassNames?.includes("isFolder"); + const isRoom = itemClassNames?.includes("isRoom"); + const isHeader = + itemClassNames?.includes("folder_header") || + itemClassNames?.includes("files_header"); + + if (isScrolling && showSkeleton) { + const list = []; + let i = 0; + + if (isHeader) { + return ( +
+ + + +
+ ); + } + + while (i < countTilesInRow) { + list.push( + , + ); + i += 1; + } + + return ( +
+ {list.map((item) => item)} +
+ ); + } + return (
{children[index]} diff --git a/packages/shared/components/infinite-loader/sub-components/List.tsx b/packages/shared/components/infinite-loader/sub-components/List.tsx index add98587e6..ed70f0b2b6 100644 --- a/packages/shared/components/infinite-loader/sub-components/List.tsx +++ b/packages/shared/components/infinite-loader/sub-components/List.tsx @@ -47,6 +47,7 @@ const ListComponent = ({ className, scroll, infoPanelVisible, + showSkeleton, }: ListComponentProps) => { const loaderRef = useRef(null); const listRef = useRef(null); @@ -89,13 +90,16 @@ const ListComponent = ({ key, index, style, + isScrolling, }: { key: string; index: number; style: React.CSSProperties; + isScrolling: boolean; }) => { const isLoaded = isItemLoaded({ index }); - if (!isLoaded) return getLoader(style, key); + if (!isLoaded || (isScrolling && showSkeleton)) + return getLoader(style, key); return (
@@ -108,10 +112,12 @@ const ListComponent = ({ index, style, key, + isScrolling, }: { index: number; style: React.CSSProperties; key: string; + isScrolling: boolean; }) => { if (!columnInfoPanelStorageName || !columnStorageName) { throw new Error("columnStorageName is required for a table view"); @@ -122,7 +128,8 @@ const ListComponent = ({ : localStorage.getItem(columnStorageName); const isLoaded = isItemLoaded({ index }); - if (!isLoaded) return getLoader(style, key); + if (!isLoaded || (isScrolling && showSkeleton)) + return getLoader(style, key); return (
+ ) : isRoom ? ( + + + + + + + + + + + + + ) : ( diff --git a/packages/shared/skeletons/tiles/Tiles.styled.ts b/packages/shared/skeletons/tiles/Tiles.styled.ts index f3ac12fa81..871cc6e965 100644 --- a/packages/shared/skeletons/tiles/Tiles.styled.ts +++ b/packages/shared/skeletons/tiles/Tiles.styled.ts @@ -120,3 +120,26 @@ export const StyledTilesWrapper = styled.div` grid-template-columns: 1fr; grid-gap: 16px; `; + +export const StyledRoomTile = styled.div` + border: ${(props) => props.theme.filesSection.tilesView.tile.border}; + border-radius: 6px; + height: 120px; +`; + +export const StyledRoomTileTopContent = styled.div` + display: grid; + grid-template-columns: 32px 1fr 24px; + gap: 8px; + align-items: center; + height: 61px; + border-bottom: ${(props) => props.theme.filesSection.tilesView.tile.border}; + padding: 0 8px 0 16px; +`; + +export const StyledRoomTileBottomContent = styled.div` + display: flex; + align-items: center; + padding: 16px; + gap: 4px; +`; diff --git a/packages/shared/skeletons/tiles/Tiles.types.ts b/packages/shared/skeletons/tiles/Tiles.types.ts index 2881313070..982ab305bc 100644 --- a/packages/shared/skeletons/tiles/Tiles.types.ts +++ b/packages/shared/skeletons/tiles/Tiles.types.ts @@ -38,4 +38,5 @@ export interface StyledBottomProps { export interface TileSkeletonProps extends RectangleSkeletonProps { isFolder?: boolean; + isRoom?: boolean; } diff --git a/packages/shared/utils/device.ts b/packages/shared/utils/device.ts index 1900a6a3cf..5ca02c86ce 100644 --- a/packages/shared/utils/device.ts +++ b/packages/shared/utils/device.ts @@ -26,6 +26,7 @@ export const INFO_PANEL_WIDTH = 400; export const TABLE_HEADER_HEIGHT = 40; +export const MAX_INFINITE_LOADER_SHIFT = 800; export function checkIsSSR() { return typeof window === "undefined"; From aaf58e66471551cd8e190f5144ddd5f83339f24d Mon Sep 17 00:00:00 2001 From: gopienkonikita Date: Tue, 6 Aug 2024 17:33:52 +0300 Subject: [PATCH 2/2] Web: Components: InfiniteLoader: fixed StyledItem styles --- .../infinite-loader/InfiniteLoader.styled.ts | 21 +++---------------- 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/packages/shared/components/infinite-loader/InfiniteLoader.styled.ts b/packages/shared/components/infinite-loader/InfiniteLoader.styled.ts index e297c56f4f..398dd9166a 100644 --- a/packages/shared/components/infinite-loader/InfiniteLoader.styled.ts +++ b/packages/shared/components/infinite-loader/InfiniteLoader.styled.ts @@ -159,27 +159,12 @@ StyledScroll.defaultProps = { const paddingCss = css` @media ${desktop} { - ${(props) => - props.theme.interfaceDirection === "rtl" - ? css` - margin-right: 1px; - padding-left: 0px; - ` - : css` - margin-left: 1px; - padding-right: 0px; - `} + margin-inline-start: 1px; + padding-inline-end: 0; } @media ${tablet} { - ${(props) => - props.theme.interfaceDirection === "rtl" - ? css` - margin-right: -1px; - ` - : css` - margin-left: -1px; - `} + margin-inline-start: -1px; } `;