diff --git a/src/components/Dataform/Dataform.tsx b/src/components/Dataform/Dataform.tsx index cbdfb0f..1395004 100644 --- a/src/components/Dataform/Dataform.tsx +++ b/src/components/Dataform/Dataform.tsx @@ -3,103 +3,117 @@ import Folders from "../Folders/Folders"; import { useFiles, useQuickFiles, useUploader } from "../../hooks/files"; import { useInfiniteScroll } from "../../hooks/infiniteScroll"; import Files from "../Files/Files"; -import { memo, useCallback, useEffect, useState } from "react"; +import { memo, useCallback, useEffect, useRef, useState } from "react"; import Spinner from "../Spinner/Spinner"; -import { useAppDispatch } from "../../hooks/store"; +import { useAppDispatch, useAppSelector } from "../../hooks/store"; import { useParams } from "react-router-dom"; import classNames from "classnames"; import { useDragAndDrop } from "../../hooks/utils"; import MultiSelectBar from "../MultiSelectBar/MultiSelectBar"; import { useFolders } from "../../hooks/folders"; -const DataForm = memo(() => { - const { - fetchNextPage: filesFetchNextPage, - isFetchingNextPage, - data: fileList, - isLoading: isLoadingFiles, - } = useFiles(); - const { isLoading: isLoadingFolders } = useFolders(); - const { isLoading: isLoadingQuickItems } = useQuickFiles(); - const dispatch = useAppDispatch(); - const { sentinelRef, reachedIntersect } = useInfiniteScroll(); - const [initialLoad, setInitialLoad] = useState(true); - const params = useParams(); - const { uploadFiles } = useUploader(); +const DataForm = memo( + ({ scrollDivRef }: { scrollDivRef: React.RefObject }) => { + const { + fetchNextPage: filesFetchNextPage, + isFetchingNextPage, + data: fileList, + isLoading: isLoadingFiles, + } = useFiles(); + const { isLoading: isLoadingFolders } = useFolders(); + const { isLoading: isLoadingQuickItems } = useQuickFiles(); + const dispatch = useAppDispatch(); + const { sentinelRef, reachedIntersect } = useInfiniteScroll(); + const [initialLoad, setInitialLoad] = useState(true); + const params = useParams(); + const { uploadFiles } = useUploader(); + const navigationMap = useAppSelector((state) => { + return state.selected.navigationMap[window.location.pathname]; + }); - const isLoading = isLoadingFiles || isLoadingFolders || isLoadingQuickItems; + const isLoading = isLoadingFiles || isLoadingFolders || isLoadingQuickItems; - useEffect(() => { - if (initialLoad) { - setInitialLoad(false); - return; - } else if (!fileList) { - return; - } - if (reachedIntersect && !isFetchingNextPage) { - filesFetchNextPage(); - } - }, [reachedIntersect, initialLoad, isFetchingNextPage]); + useEffect(() => { + if (initialLoad) { + setInitialLoad(false); + return; + } else if (!fileList) { + return; + } + if (reachedIntersect && !isFetchingNextPage) { + filesFetchNextPage(); + } + }, [reachedIntersect, initialLoad, isFetchingNextPage]); - const addFile = useCallback( - (files: FileList) => { - uploadFiles(files); - }, - [params.id] - ); + useEffect(() => { + if (!isLoading && navigationMap) { + scrollDivRef.current?.scrollTo(0, navigationMap.scrollTop); + } else if (!isLoading) { + scrollDivRef.current?.scrollTo(0, 0); + } + }, [isLoading, navigationMap, window.location.pathname]); - const { - isDraggingFile, - onDragDropEvent, - onDragEvent, - onDragEnterEvent, - stopDrag, - } = useDragAndDrop(addFile); + const addFile = useCallback( + (files: FileList) => { + uploadFiles(files); + }, + [params.id] + ); - return ( -
- {!isLoading && ( -
-
- + const { + isDraggingFile, + onDragDropEvent, + onDragEvent, + onDragEnterEvent, + stopDrag, + } = useDragAndDrop(addFile); + + return ( +
+ {!isLoading && ( +
+
+ +
+ + + + + +
+ )} - + {isLoading && ( +
+ +
+ )} + {/* @ts-ignore */} +
- - - -
- )} - - {isLoading && ( -
- -
- )} - {/* @ts-ignore */} -
- - {/* TODO: Change this spinner name */} - {isFetchingNextPage && ( -
- -
- )} -
- ); -}); + {/* TODO: Change this spinner name */} + {isFetchingNextPage && ( +
+ +
+ )} +
+ ); + } +); export default DataForm; diff --git a/src/components/FolderItem/FolderItem.tsx b/src/components/FolderItem/FolderItem.tsx index 9b60837..446bb29 100644 --- a/src/components/FolderItem/FolderItem.tsx +++ b/src/components/FolderItem/FolderItem.tsx @@ -6,16 +6,21 @@ import { useNavigate } from "react-router-dom"; import mobilecheck from "../../utils/mobileCheck"; import moment from "moment"; import { useAppDispatch, useAppSelector } from "../../hooks/store"; -import { setMainSelect, setMultiSelectMode } from "../../reducers/selected"; +import { + addNavigationMap, + setMainSelect, + setMultiSelectMode, +} from "../../reducers/selected"; import { useUtils } from "../../hooks/utils"; import { FolderInterface } from "../../types/folders"; interface FolderItemProps { folder: FolderInterface; + scrollDivRef: React.RefObject; } const FolderItem: React.FC = memo((props) => { - const { folder } = props; + const { folder, scrollDivRef } = props; const elementSelected = useAppSelector((state) => { if (state.selected.mainSection.type !== "folder") return false; return state.selected.mainSection.id === folder._id; @@ -77,6 +82,12 @@ const FolderItem: React.FC = memo((props) => { } if (singleClickFolders || currentDate - lastSelected.current < 1500) { + dispatch( + addNavigationMap({ + url: window.location.pathname, + scrollTop: scrollDivRef.current?.scrollTop || 0, + }) + ); if (isTrash) { navigate(`/folder-trash/${folder._id}`); } else { diff --git a/src/components/Folders/Folders.tsx b/src/components/Folders/Folders.tsx index 278ad42..20992ff 100644 --- a/src/components/Folders/Folders.tsx +++ b/src/components/Folders/Folders.tsx @@ -6,137 +6,143 @@ import { useUtils } from "../../hooks/utils"; import { useAppDispatch, useAppSelector } from "../../hooks/store"; import { setSortBy } from "../../reducers/filter"; -const Folders = memo(() => { - const { data: folders } = useFolders(false); - const { isHome, isTrash, isSearch } = useUtils(); - const sortBy = useAppSelector((state) => state.filter.sortBy); - const dispatch = useAppDispatch(); +const Folders = memo( + ({ scrollDivRef }: { scrollDivRef: React.RefObject }) => { + const { data: folders } = useFolders(false); + const { isHome, isTrash, isSearch } = useUtils(); + const sortBy = useAppSelector((state) => state.filter.sortBy); + const dispatch = useAppDispatch(); - const switchOrderSortBy = useCallback(() => { - let newSortBy = ""; - switch (sortBy) { - case "date_asc": { - newSortBy = "date_desc"; - break; - } - case "date_desc": { - newSortBy = "date_asc"; - break; - } - case "alp_asc": { - newSortBy = "alp_desc"; - break; - } - case "alp_desc": { - newSortBy = "alp_asc"; - break; - } - default: { - newSortBy = "date_desc"; - break; - } - } - - dispatch(setSortBy(newSortBy)); - }, [sortBy]); - - const switchTypeOrderBy = useCallback( - (e: any) => { - const value = e.target.value; - - let newSortBy = "date_desc"; - - if (value === "date") { - if (sortBy.includes("asc")) { - newSortBy = "date_asc"; - } else { + const switchOrderSortBy = useCallback(() => { + let newSortBy = ""; + switch (sortBy) { + case "date_asc": { newSortBy = "date_desc"; + break; } - } else if (value === "name") { - if (sortBy.includes("asc")) { - newSortBy = "alp_asc"; - } else { + case "date_desc": { + newSortBy = "date_asc"; + break; + } + case "alp_asc": { newSortBy = "alp_desc"; + break; + } + case "alp_desc": { + newSortBy = "alp_asc"; + break; + } + default: { + newSortBy = "date_desc"; + break; } } dispatch(setSortBy(newSortBy)); - }, - [sortBy] - ); + }, [sortBy]); - const title = useMemo(() => { - if (isTrash) { - return "Trash"; - } else if (isSearch) { - return "Search"; - } else { - return folders?.length === 0 ? "No Folders" : "Folders"; - } - }, [isHome, isTrash, isSearch, folders?.length]); + const switchTypeOrderBy = useCallback( + (e: any) => { + const value = e.target.value; - return ( -
-
-

- {title} -

- - ); -}); + ); + } +); export default Folders; diff --git a/src/components/LeftSection/LeftSection.tsx b/src/components/LeftSection/LeftSection.tsx index 98ef2f3..7b0b9ff 100644 --- a/src/components/LeftSection/LeftSection.tsx +++ b/src/components/LeftSection/LeftSection.tsx @@ -10,8 +10,13 @@ import { closeDrawer } from "../../reducers/leftSection"; import SettingsIcon from "../../icons/SettingsIcon"; import ChevronSolid from "../../icons/ChevronSolid"; import HomeIconOutline from "../../icons/HomeIconOutline"; +import { addNavigationMap } from "../../reducers/selected"; -const LeftSection = () => { +const LeftSection = ({ + scrollDivRef, +}: { + scrollDivRef: React.RefObject; +}) => { const [isDropdownOpen, setIsDropdownOpen] = useState(false); const leftSectionOpen = useAppSelector((state) => state.leftSection.drawOpen); const { isHome, isHomeFolder, isTrash, isMedia, isSettings } = useUtils(); @@ -33,21 +38,45 @@ const LeftSection = () => { const goHome = () => { dispatch(closeDrawer()); + dispatch( + addNavigationMap({ + url: window.location.pathname, + scrollTop: scrollDivRef.current?.scrollTop || 0, + }) + ); navigate("/home"); }; const goTrash = () => { dispatch(closeDrawer()); + dispatch( + addNavigationMap({ + url: window.location.pathname, + scrollTop: scrollDivRef.current?.scrollTop || 0, + }) + ); navigate("/trash"); }; const goMedia = () => { dispatch(closeDrawer()); + dispatch( + addNavigationMap({ + url: window.location.pathname, + scrollTop: scrollDivRef.current?.scrollTop || 0, + }) + ); navigate("/media"); }; const goSettings = () => { dispatch(closeDrawer()); + dispatch( + addNavigationMap({ + url: window.location.pathname, + scrollTop: scrollDivRef.current?.scrollTop || 0, + }) + ); navigate("/settings"); }; diff --git a/src/components/MainSection/MainSection.tsx b/src/components/MainSection/MainSection.tsx index d140207..0fb5f61 100644 --- a/src/components/MainSection/MainSection.tsx +++ b/src/components/MainSection/MainSection.tsx @@ -1,6 +1,6 @@ import DataForm from "../Dataform/Dataform"; import RightSection from "../RightSection/RightSection"; -import { memo } from "react"; +import { memo, useRef } from "react"; import LeftSection from "../LeftSection/LeftSection"; import { useUtils } from "../../hooks/utils"; import Medias from "../Medias/Medias"; @@ -20,6 +20,7 @@ const MainSection = memo(() => { const moveModalItemType = useAppSelector( (state) => state.selected.moveModal.type ); + const scrollDivRef = useRef(null); const isMediaSelected = popupModalItem?.metadata.isVideo || popupModalItem?.metadata.hasThumbnail; @@ -40,9 +41,13 @@ const MainSection = memo(() => { {moveModalItemType && }
- + - {!isMedia ? : } + {!isMedia ? ( + + ) : ( + + )}
diff --git a/src/components/Medias/Medias.tsx b/src/components/Medias/Medias.tsx index 53b4a30..f66af4c 100644 --- a/src/components/Medias/Medias.tsx +++ b/src/components/Medias/Medias.tsx @@ -7,133 +7,150 @@ import { useInfiniteScroll } from "../../hooks/infiniteScroll"; import { useAppDispatch, useAppSelector } from "../../hooks/store"; import { setMediaFilter, setSortBy } from "../../reducers/filter"; -const Medias = memo(() => { - const { - data: files, - isFetchingNextPage, - fetchNextPage: filesFetchNextPage, - } = useFiles(); - const [initialLoad, setInitialLoad] = useState(true); - const { sentinelRef, reachedIntersect } = useInfiniteScroll(); - const sortBy = useAppSelector((state) => state.filter.sortBy); - const mediaFilter = useAppSelector((state) => state.filter.mediaFilter); - const dispatch = useAppDispatch(); +const Medias = memo( + ({ scrollDivRef }: { scrollDivRef: React.RefObject }) => { + const { + data: files, + isFetchingNextPage, + fetchNextPage: filesFetchNextPage, + } = useFiles(); + const [initialLoad, setInitialLoad] = useState(true); + const { sentinelRef, reachedIntersect } = useInfiniteScroll(); + const sortBy = useAppSelector((state) => state.filter.sortBy); + const mediaFilter = useAppSelector((state) => state.filter.mediaFilter); + const navigationMap = useAppSelector((state) => { + return state.selected.navigationMap[window.location.pathname]; + }); - useEffect(() => { - if (initialLoad) { - setInitialLoad(false); - return; - } else if (!files) { - return; - } - if (reachedIntersect && !isFetchingNextPage) { - filesFetchNextPage(); - } - }, [reachedIntersect, initialLoad, isFetchingNextPage]); + const dispatch = useAppDispatch(); - const switchOrderSortBy = useCallback(() => { - let newSortBy = ""; - switch (sortBy) { - case "date_asc": { - newSortBy = "date_desc"; - break; + useEffect(() => { + if (initialLoad) { + setInitialLoad(false); + return; + } else if (!files) { + return; } - case "date_desc": { - newSortBy = "date_asc"; - break; + if (reachedIntersect && !isFetchingNextPage) { + filesFetchNextPage(); } - case "alp_asc": { - newSortBy = "alp_desc"; - break; + }, [reachedIntersect, initialLoad, isFetchingNextPage]); + + useEffect(() => { + if (!initialLoad && navigationMap) { + scrollDivRef.current?.scrollTo(0, navigationMap.scrollTop); + } else if (!initialLoad) { + scrollDivRef.current?.scrollTo(0, 0); } - case "alp_desc": { - newSortBy = "alp_asc"; - break; + }, [initialLoad, navigationMap, window.location.pathname]); + + const switchOrderSortBy = useCallback(() => { + let newSortBy = ""; + switch (sortBy) { + case "date_asc": { + newSortBy = "date_desc"; + break; + } + case "date_desc": { + newSortBy = "date_asc"; + break; + } + case "alp_asc": { + newSortBy = "alp_desc"; + break; + } + case "alp_desc": { + newSortBy = "alp_asc"; + break; + } + default: { + newSortBy = "date_desc"; + break; + } } - default: { - newSortBy = "date_desc"; - break; + + dispatch(setSortBy(newSortBy)); + }, [sortBy]); + + const mediaFilterOnChange = (e: React.ChangeEvent) => { + const value = e.target.value; + + dispatch(setMediaFilter(value)); + }; + + const title = useMemo(() => { + if (mediaFilter === "all") { + return "Photos and Videos"; + } else if (mediaFilter === "photos") { + return "Photos"; + } else if (mediaFilter === "videos") { + return "Videos"; } - } + }, [mediaFilter]); - dispatch(setSortBy(newSortBy)); - }, [sortBy]); - - const mediaFilterOnChange = (e: React.ChangeEvent) => { - const value = e.target.value; - - dispatch(setMediaFilter(value)); - }; - - const title = useMemo(() => { - if (mediaFilter === "all") { - return "Photos and Videos"; - } else if (mediaFilter === "photos") { - return "Photos"; - } else if (mediaFilter === "videos") { - return "Videos"; - } - }, [mediaFilter]); - - return ( -
-
-

{title}

-
- - - - - - - - -
-
+ return (
-
- +
+

{title}

+
+ + + + + + + + +
- {files?.pages.map((filePage, index) => ( - - {filePage.map((file) => ( - - ))} - - ))} +
+
+ +
+ {files?.pages.map((filePage, index) => ( + + {filePage.map((file) => ( + + ))} + + ))} +
+ {/* @ts-ignore */} +
- {/* @ts-ignore */} -
-
- ); -}); + ); + } +); export default Medias; diff --git a/src/reducers/selected.ts b/src/reducers/selected.ts index 660c388..c8f1345 100644 --- a/src/reducers/selected.ts +++ b/src/reducers/selected.ts @@ -30,6 +30,12 @@ export interface SelectedStateType { file: FileInterface | null; }; moveModal: MoveStateType; + navigationMap: { + [key: string]: { + url: string; + scrollTop: number; + }; + }; } const initialState: SelectedStateType = { @@ -54,6 +60,7 @@ const initialState: SelectedStateType = { file: null, folder: null, }, + navigationMap: {}, }; const selectedSlice = createSlice({ @@ -143,6 +150,20 @@ const selectedSlice = createSlice({ folder: null, }; }, + addNavigationMap: ( + state, + action: PayloadAction<{ + url: string; + scrollTop: number; + }> + ) => { + const navigationMap = state.navigationMap; + navigationMap[action.payload.url] = { + url: action.payload.url, + scrollTop: action.payload.scrollTop, + }; + state.navigationMap = navigationMap; + }, }, }); @@ -157,6 +178,7 @@ export const { resetShareModal, setMoveModal, resetMoveModal, + addNavigationMap, } = selectedSlice.actions; export default selectedSlice.reducer;