From 4a8794b7be64de813b4428912d99d175d1b7a5a0 Mon Sep 17 00:00:00 2001 From: subnub Date: Tue, 2 Jul 2024 02:21:28 -0400 Subject: [PATCH] mobile UI improvements and code cleanup --- src/components/Dataform/index.jsx | 2 +- src/components/FileItem/index.jsx | 2 +- src/components/Files/index.jsx | 5 +- src/components/Header/index.tsx | 23 +- src/components/LeftSection/LeftSection.jsx | 129 ---------- src/components/LeftSection/index.jsx | 272 +++++++++++---------- src/components/Medias/index.tsx | 2 +- src/components/MultiSelectBar/index.tsx | 2 +- src/components/ParentBar/ParentBar.jsx | 4 +- src/components/QuickAccess/index.jsx | 4 +- src/components/SearchBar/index.tsx | 8 +- src/hooks/utils.ts | 4 +- src/icons/MenuIcon.tsx | 15 ++ src/reducers/leftSection.ts | 22 ++ src/store/configureStore.ts | 2 + 15 files changed, 219 insertions(+), 277 deletions(-) delete mode 100644 src/components/LeftSection/LeftSection.jsx create mode 100644 src/icons/MenuIcon.tsx create mode 100644 src/reducers/leftSection.ts diff --git a/src/components/Dataform/index.jsx b/src/components/Dataform/index.jsx index e1102cc..412867b 100644 --- a/src/components/Dataform/index.jsx +++ b/src/components/Dataform/index.jsx @@ -73,7 +73,7 @@ const DataForm = memo(() => { > {!isLoading && (
-
+
diff --git a/src/components/FileItem/index.jsx b/src/components/FileItem/index.jsx index 5bcdd08..774b01f 100644 --- a/src/components/FileItem/index.jsx +++ b/src/components/FileItem/index.jsx @@ -220,7 +220,7 @@ const FileItem = React.memo((props) => { {hasThumbnail ? (
diff --git a/src/components/Files/index.jsx b/src/components/Files/index.jsx index 08b3e63..d9452b4 100644 --- a/src/components/Files/index.jsx +++ b/src/components/Files/index.jsx @@ -39,12 +39,9 @@ const Files = memo(() => { )} {!isHome && ( -
+
-

- Files -

)} diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx index b5627a2..640ade3 100644 --- a/src/components/Header/index.tsx +++ b/src/components/Header/index.tsx @@ -1,12 +1,22 @@ import { useNavigate } from "react-router-dom"; import SearchBar from "../SearchBar"; +import MenuIcon from "../../icons/MenuIcon"; +import { useAppDispatch, useAppSelector } from "../../hooks/store"; +import { useCallback, useMemo } from "react"; +import { toggleDrawer } from "../../reducers/leftSection"; const Header = () => { + const drawerOpen = useAppSelector((state) => state.leftSection.drawOpen); + const dispatch = useAppDispatch(); const navigate = useNavigate(); + + const toggleDrawerClick = useCallback(() => { + dispatch(toggleDrawer()); + }, [toggleDrawer]); return (
-
+ +
+ + + +
-
+
{ - const [isDropdownOpen, setIsDropdownOpen] = useState(false); - const { isHome, isTrash, isMedia } = useUtils(); - const navigate = useNavigate(); - const addNewDisabled = useRef(false); - - const openDropdown = useCallback(() => { - if (addNewDisabled.current) return; - setIsDropdownOpen(true); - }, []); - - const closeDropdown = useCallback(() => { - addNewDisabled.current = true; - setIsDropdownOpen(false); - // Clicking out of bounds on the add new button will cause it to reopen - setTimeout(() => (addNewDisabled.current = false), 300); - }, []); - - const goHome = () => { - navigate("/home"); - }; - - const goTrash = () => { - navigate("/trash"); - }; - - const goMedia = () => { - navigate("/media"); - }; - - return ( -
-
-
-
- -

ADD NEW

- - dropselect - -
- {/* TODO: Remove this props */} - {isDropdownOpen && ( - - )} -
-
- -
-
-
- -
-
- -
-
-
- ); -}; - -export default LeftSection; diff --git a/src/components/LeftSection/index.jsx b/src/components/LeftSection/index.jsx index 5ba00a0..979e149 100644 --- a/src/components/LeftSection/index.jsx +++ b/src/components/LeftSection/index.jsx @@ -1,145 +1,155 @@ -import LeftSection from "./LeftSection"; -import { showAddOptions } from "../../actions/addOptions"; -import { startAddFile } from "../../actions/files"; -import { startAddFolder } from "../../actions/folders"; -import Swal from "sweetalert2"; -import { connect } from "react-redux"; -import React from "react"; -import { openUploadOverlay, setLeftSectionMode } from "../../actions/main"; +import React, { useCallback, useRef, useState } from "react"; +import { useNavigate, useParams } from "react-router-dom"; +import { createFolderAPI } from "../../api/foldersAPI"; +import { useFoldersClient } from "../../hooks/folders"; +import { showCreateFolderPopup } from "../../popups/folder"; +import { useClickOutOfBounds, useUtils } from "../../hooks/utils"; +import AddNewDropdown from "../AddNewDropdown"; +import HomeListIcon from "../../icons/HomeListIcon"; +import TrashIcon from "../../icons/TrashIcon"; +import classNames from "classnames"; +import PhotoIcon from "../../icons/PhotoIcon"; +import { useAppDispatch, useAppSelector } from "../../hooks/store"; +import { closeDrawer } from "../../reducers/leftSection"; -class LeftSectionContainer extends React.Component { - constructor(props) { - super(props); +const LeftSection = (props) => { + const [isDropdownOpen, setIsDropdownOpen] = useState(false); + const leftSectionOpen = useAppSelector((state) => state.leftSection.drawOpen); + const { isHome, isTrash, isMedia } = useUtils(); + const dispatch = useAppDispatch(); + const navigate = useNavigate(); + const addNewDisabled = useRef(false); - this.wrapperRef = React.createRef(); - this.uploadInput = React.createRef(); + const openDropdown = useCallback(() => { + if (addNewDisabled.current) return; + setIsDropdownOpen(true); + }, []); - this.leftSectionRef = React.createRef(); + const closeDropdown = useCallback(() => { + addNewDisabled.current = true; + setIsDropdownOpen(false); + // Clicking out of bounds on the add new button will cause it to reopen + setTimeout(() => (addNewDisabled.current = false), 300); + }, []); - this.state = { - open: false, - hideFolderTree: false, - }; - } + const goHome = () => { + closeDrawerEvent(); + navigate("/home"); + }; - createFolder = async (e) => { - let inputValue = ""; + const goTrash = () => { + closeDrawerEvent(); + navigate("/trash"); + }; - const { value: folderName } = await Swal.fire({ - title: "Enter Folder Name", - input: "text", - inputValue: inputValue, - showCancelButton: true, - inputValidator: (value) => { - if (!value) { - return "Please Enter a Name"; - } - }, - }); + const goMedia = () => { + closeDrawerEvent(); + navigate("/media"); + }; - if (folderName === undefined || folderName === null) { + const closeDrawerEvent = (e) => { + if ( + e && + (!leftSectionOpen || + e.target.id === "search-bar" || + e.target.id === "menu-icon") + ) { return; } - const parent = this.props.parent; - const owner = this.props.auth.id; - const parentList = this.props.parentList; - const isGoogle = this.props.isGoogle; - - this.props.dispatch( - startAddFolder(folderName, owner, parent, parentList, isGoogle) - ); - this.showDropDown(); + dispatch(closeDrawer()); }; - handleClickOutside = (e) => { - if ( - this.leftSectionRef && - !this.leftSectionRef.current.contains(event.target) - ) { - if (this.props.leftSectionMode === "open") { - this.props.dispatch(setLeftSectionMode("close")); - } - } - }; + const { wrapperRef } = useClickOutOfBounds(closeDrawerEvent); - componentDidMount = () => { - document.addEventListener("mousedown", this.handleClickOutside); + return ( +
+
+
+
+ +

+ ADD NEW +

+ + dropselect + +
+ {/* TODO: Remove this props */} + {isDropdownOpen && ( + + )} +
+
+ +
+
+
+ +
+
+ +
+
+
+ ); +}; - const hideFolderTree = localStorage.getItem("hide-folder-tree"); - - if (hideFolderTree) { - this.setState(() => ({ - hideFolderTree, - })); - } - }; - - componentWillUnmount = () => { - document.removeEventListener("mousedown", this.handleClickOutside); - }; - - addButtonEvent = () => { - const currentAddOptions = !this.props.showAddOptions; - this.props.dispatch(showAddOptions(currentAddOptions)); - }; - - handleUpload = (e) => { - e.preventDefault(); - console.log("handle upload"); - - this.props.dispatch( - startAddFile( - this.uploadInput.current, - this.props.parent, - this.props.parentList, - this.props.storageSwitcher - ) - ); - this.uploadInput.current.value = ""; - }; - - showDropDown = () => { - this.setState(() => { - return { - ...this.state, - open: !this.state.open, - }; - }); - }; - - showUploadOverlay = () => { - this.showDropDown(); - this.props.dispatch(openUploadOverlay()); - }; - - render() { - return ( - - ); - } -} - -const connectPropToState = (state) => ({ - auth: state.auth, - parent: state.parent.parent, - parentList: state.parent.parentList, - storage: state.storage, - showAddOptions: state.addOptions.showAddOptions, - isGoogle: state.filter.isGoogle, - storageSwitcher: state.storageSwitcher.selected, - leftSectionMode: state.main.leftSectionMode, -}); - -export default connect(connectPropToState)(LeftSectionContainer); +export default LeftSection; diff --git a/src/components/Medias/index.tsx b/src/components/Medias/index.tsx index fd22945..72e4c17 100644 --- a/src/components/Medias/index.tsx +++ b/src/components/Medias/index.tsx @@ -33,7 +33,7 @@ const Medias = memo(() => { "grid grid-cols-[repeat(auto-fill,minmax(100px,1fr))] gap-[10px]" )} > -
+
{files?.pages.map((filePage, index) => ( diff --git a/src/components/MultiSelectBar/index.tsx b/src/components/MultiSelectBar/index.tsx index 8b35dd5..bdc3119 100644 --- a/src/components/MultiSelectBar/index.tsx +++ b/src/components/MultiSelectBar/index.tsx @@ -106,7 +106,7 @@ const MultiSelectBar: React.FC = () => { if (!multiSelectMode) return
; return ( -
+
diff --git a/src/components/ParentBar/ParentBar.jsx b/src/components/ParentBar/ParentBar.jsx index 37a7b19..6eca721 100644 --- a/src/components/ParentBar/ParentBar.jsx +++ b/src/components/ParentBar/ParentBar.jsx @@ -34,7 +34,7 @@ const ParentBar = memo(() => { // } return ( -
+
{

{folder.name}

diff --git a/src/components/QuickAccess/index.jsx b/src/components/QuickAccess/index.jsx index 0701602..0a2c207 100644 --- a/src/components/QuickAccess/index.jsx +++ b/src/components/QuickAccess/index.jsx @@ -44,8 +44,8 @@ const QuickAccess = memo(() => { ? "justify-center xs:justify-normal" : "justify-normal", { - "max-h-36 sm:max-h-40": !quickAccessExpanded, - "max-h-[720px] sm:max-h-[665px] quickAccessOne:max-h-[1000px] quickAccessTwo:max-h-[660px] quickAccessThree:max-h-[490px]": + "max-h-32 sm:max-h-40": !quickAccessExpanded, + "max-h-[700px] sm:max-h-[665px] quickAccessOne:max-h-[1000px] quickAccessTwo:max-h-[660px] quickAccessThree:max-h-[490px]": quickAccessExpanded, } )} diff --git a/src/components/SearchBar/index.tsx b/src/components/SearchBar/index.tsx index 46ee0c7..71ba3f1 100644 --- a/src/components/SearchBar/index.tsx +++ b/src/components/SearchBar/index.tsx @@ -10,7 +10,7 @@ import { FileInterface } from "../../types/file"; import { setPopupFile } from "../../actions/popupFile"; import Spinner from "../Spinner"; import classNames from "classnames"; -import { is } from "@babel/types"; +import { closeDrawer } from "../../reducers/leftSection"; const SearchBar = memo(() => { const [searchText, setSearchText] = useState(""); @@ -85,6 +85,10 @@ const SearchBar = memo(() => { resetState(); }; + const onFocus = () => { + dispatch(closeDrawer()); + }; + const searchTextPlaceholder = useMemo(() => { if (isMedia) { return "Search Media"; @@ -121,6 +125,8 @@ const SearchBar = memo(() => { value={searchText} placeholder={searchTextPlaceholder} className="w-full min-h-[42px] border border-[#BEC9D3] pl-[45px] pr-[15px] text-[16px] text-black rounded-[5px]" + onFocus={onFocus} + id="search-bar" />
{ return { isHome, isTrash, isMedia }; }; -export const useClickOutOfBounds = (outOfBoundsCallback: () => any) => { +export const useClickOutOfBounds = (outOfBoundsCallback: (e: any) => any) => { console.log("out"); const wrapperRef = useRef(null); // TODO: Remove this any const outOfBoundsClickCheck = useCallback( (e: any) => { if (wrapperRef && !wrapperRef.current?.contains(e.target as Node)) { - outOfBoundsCallback(); + outOfBoundsCallback(e); } }, [outOfBoundsCallback] diff --git a/src/icons/MenuIcon.tsx b/src/icons/MenuIcon.tsx new file mode 100644 index 0000000..13b6c05 --- /dev/null +++ b/src/icons/MenuIcon.tsx @@ -0,0 +1,15 @@ +type MenuIconType = React.SVGAttributes; + +const MenuIcon: React.FC = (props) => { + return ( + + menu + + + ); +}; + +export default MenuIcon; diff --git a/src/reducers/leftSection.ts b/src/reducers/leftSection.ts new file mode 100644 index 0000000..e3288d8 --- /dev/null +++ b/src/reducers/leftSection.ts @@ -0,0 +1,22 @@ +import { createSlice } from "@reduxjs/toolkit"; + +const initialState = { + drawOpen: false, +}; + +const leftSectionSlice = createSlice({ + name: "selected", + initialState, + reducers: { + toggleDrawer: (state) => { + state.drawOpen = !state.drawOpen; + }, + closeDrawer: (state) => { + state.drawOpen = false; + }, + }, +}); + +export const { toggleDrawer, closeDrawer } = leftSectionSlice.actions; + +export default leftSectionSlice.reducer; diff --git a/src/store/configureStore.ts b/src/store/configureStore.ts index 30a67f5..55b5145 100755 --- a/src/store/configureStore.ts +++ b/src/store/configureStore.ts @@ -19,6 +19,7 @@ import folderTreeReducer from "../reducers/folderTree"; import uploadStorageSwitcherReducer from "../reducers/uploadStorageSwitcher"; import mobileContextMenuReducer from "../reducers/mobileContextMenu"; import selectedReducer from "../reducers/selected"; +import leftSectionReducer from "../reducers/leftSection"; //const composeEnchancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; @@ -30,6 +31,7 @@ const store = configureStore({ folders: folderReducer, filter: filterReducer, selected: selectedReducer, + leftSection: leftSectionReducer, selectedItem: selectedItemReducer, uploads: uploadsReducer, storage: storageReducer,