Skip to content

Commit

Permalink
adds hooks for window size
Browse files Browse the repository at this point in the history
 - makes mobile view prettier for some of projectView
  • Loading branch information
Andrea-Papaleo committed May 9, 2024
1 parent bcacaf2 commit 73b0edc
Show file tree
Hide file tree
Showing 13 changed files with 219 additions and 64 deletions.
80 changes: 56 additions & 24 deletions src/components/app-bars/ProjectToolbar/ProjectToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@ import {
Typography,
TextField,
FormControl,
Menu,
} from "@mui/material";
import {
ZoomOut as ZoomOutIcon,
ZoomIn as ZoomInIcon,
Search as SearchIcon,
Add as AddIcon,
Remove as RemoveIcon,
} from "@mui/icons-material";

import { LogoLoader } from "components/styled-components";
Expand All @@ -25,6 +29,7 @@ import {
selectLoadPercent,
selectProjectName,
} from "store/project/selectors";
import { useMenu, useMobileView } from "hooks";

const minZoom = 0.6;
const maxZoom = 4;
Expand All @@ -37,6 +42,8 @@ export const ProjectToolbar = () => {
const [value, setValue] = useState<number>(1);
const [newProjectName, setNewProjectName] = useState<string>(projectName);
const inputRef = useRef<HTMLInputElement>(null);
const isMobile = useMobileView();
const { onOpen, onClose, open, anchorEl } = useMenu();

const handleSizeChange = (event: Event, newValue: number | number[]) => {
setValue(newValue as number);
Expand Down Expand Up @@ -111,30 +118,55 @@ export const ProjectToolbar = () => {

<Box sx={{ flexGrow: 1 }} />

<SortSelection />
<Button onClick={onZoomOut}>
<ZoomOutIcon
sx={(theme) => ({
marginLeft: theme.spacing(1),
})}
/>
</Button>

<Slider
value={value}
min={minZoom}
max={maxZoom}
step={0.1}
onChange={handleSizeChange}
sx={{ width: "10%" }}
/>
<Button onClick={onZoomIn}>
<ZoomInIcon
sx={(theme) => ({
marginRight: theme.spacing(1),
})}
/>
</Button>
{isMobile ? (
<>
<Button onClick={onOpen}>
<SearchIcon />
</Button>
<Menu anchorEl={anchorEl} open={open} onClose={onClose}>
<Box display="flex" flexDirection="column" alignItems="center">
<AddIcon />
<Slider
orientation="vertical"
value={value}
min={minZoom}
max={maxZoom}
step={0.1}
onChange={handleSizeChange}
sx={{ height: (maxZoom - minZoom) * 20 + "px", my: 1, mr: 0 }}
/>
<RemoveIcon />
</Box>
</Menu>
</>
) : (
<>
<SortSelection />
<Button onClick={onZoomOut}>
<ZoomOutIcon
sx={(theme) => ({
marginLeft: theme.spacing(1),
})}
/>
</Button>

<Slider
value={value}
min={minZoom}
max={maxZoom}
step={0.1}
onChange={handleSizeChange}
sx={{ width: "10%" }}
/>
<Button onClick={onZoomIn}>
<ZoomInIcon
sx={(theme) => ({
marginRight: theme.spacing(1),
})}
/>
</Button>
</>
)}
</Toolbar>
);
};
4 changes: 4 additions & 0 deletions src/components/dialogs/CreateKindDialog/CreateKindDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type CreateCategoriesDialogProps = {
withContainedCategories?: string[];
open: boolean;
changesPermanent?: boolean;
secondaryAction?: () => void;
};

export const CreateKindDialog = ({
Expand All @@ -21,6 +22,7 @@ export const CreateKindDialog = ({
withContainedCategories = [],
open,
changesPermanent,
secondaryAction,
}: CreateCategoriesDialogProps) => {
const dispatch = useDispatch();
const existingKinds = useSelector(selectAllKindIds);
Expand Down Expand Up @@ -81,6 +83,8 @@ export const CreateKindDialog = ({
})
);
});
secondaryAction && secondaryAction();
onClose();
};

return (
Expand Down
51 changes: 47 additions & 4 deletions src/components/drawers/ImageToolDrawer/ImageToolDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,49 @@ import React, { ReactElement, useState } from "react";
import { Badge, Drawer, ListItem, ListItemIcon, useTheme } from "@mui/material";
import FilterAltOutlinedIcon from "@mui/icons-material/FilterAltOutlined";
import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined";
import FolderOpenIcon from "@mui/icons-material/FolderOpen";
import SortIcon from "@mui/icons-material/Sort";
import ScatterPlotIcon from "@mui/icons-material/ScatterPlot";
import LabelIcon from "@mui/icons-material/Label";
import { FileList } from "components/lists";
import { CategoriesList } from "components/lists";

import { FilterOptions, InformationOptions } from "./tool-options-drawer";
import { useTranslation } from "hooks";
import { useMobileView, useTranslation } from "hooks";
import { ToolOptionsDrawer } from "./tool-options-drawer/ToolOptionsDrawer/ToolOptionsDrawer";
import { AppBarOffset } from "components/styled-components";
import { AppBarOffset, SortSelection } from "components/styled-components";
import { dimensions } from "utils/common/constants";
import { useSelector } from "react-redux";
import { ToolHotkeyTitle, TooltipCard } from "components/tooltips";
import { selectActiveFilteredStateHasFilters } from "store/project/selectors";
import { ModelTaskSection } from "../ProjectDrawer/ModelTaskSection";

export type OperationType = {
icon: (color: string) => ReactElement;
name: string;
description: string;
options: ReactElement;
hotkey: string;
mobile?: boolean;
};

const imageTools: Record<string, OperationType> = {
fileIO: {
icon: (color) => <FolderOpenIcon sx={{ color }} />,
name: "fileIO",
description: "-",
options: <FileList />,
hotkey: "O",
mobile: true,
},
sort: {
icon: (color) => <SortIcon sx={{ color }} />,
name: "sort",
description: "-",
options: <SortSelection />,
hotkey: "S",
mobile: true,
},
filters: {
icon: (color) => <FilterAltOutlinedIcon sx={{ color: color }} />,
name: "filters",
Expand All @@ -36,6 +60,22 @@ const imageTools: Record<string, OperationType> = {
options: <InformationOptions />,
hotkey: "I",
},
learning: {
icon: (color) => <ScatterPlotIcon sx={{ color }} />,
name: "learning",
description: "-",
options: <ModelTaskSection />,
hotkey: "L",
mobile: true,
},
categories: {
icon: (color) => <LabelIcon sx={{ color }} />,
name: "categories",
description: "-",
options: <CategoriesList />,
hotkey: "C",
mobile: true,
},
};

//TODO: Icon button
Expand All @@ -45,6 +85,7 @@ export const ImageToolDrawer = () => {
const [isOpen, setIsOpen] = useState<boolean>(false);
const filtersExist = useSelector(selectActiveFilteredStateHasFilters);
const t = useTranslation();
const isMobile = useMobileView();

const handleSelectTool = (toolName: string) => {
if (activeTool === undefined) {
Expand All @@ -62,7 +103,7 @@ export const ImageToolDrawer = () => {

return (
<>
{activeTool && (
{activeTool && (!imageTools[activeTool].mobile || isMobile) && (
<ToolOptionsDrawer
optionsVisibility={isOpen}
toolType={imageTools[activeTool]}
Expand All @@ -85,7 +126,7 @@ export const ImageToolDrawer = () => {
>
<AppBarOffset />
{Object.values(imageTools).map((tool) => {
return (
return !tool.mobile || isMobile ? (
<TooltipCard
key={`tool-drawer-${tool.name}`}
description={
Expand Down Expand Up @@ -121,6 +162,8 @@ export const ImageToolDrawer = () => {
</ListItemIcon>
</ListItem>
</TooltipCard>
) : (
<React.Fragment key={`tool-drawer-${tool.name}`}></React.Fragment>
);
})}
</Drawer>
Expand Down
6 changes: 5 additions & 1 deletion src/components/drawers/ProjectDrawer/ProjectDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@ import { BaseAppDrawer } from "../BaseAppDrawer";
import { FileList } from "components/lists";
import { CategoriesList } from "components/lists";
import { ModelTaskSection } from "./ModelTaskSection";
import { useMobileView } from "hooks";

export const ProjectDrawer = () => {
return (
const isMobile = useMobileView();
return isMobile ? (
<></>
) : (
<BaseAppDrawer>
<AppBarOffset />

Expand Down
20 changes: 17 additions & 3 deletions src/components/menus/AddKindMenu/AddKindMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import React from "react";
import { BaseMenu } from "../BaseMenu";
import { MenuItem, Typography } from "@mui/material";
import { CreateKindDialog } from "components/dialogs";
import { useDialog } from "hooks";
import { useDispatch } from "react-redux";
import { useDialog, useMobileView } from "hooks";
import { useDispatch, useSelector } from "react-redux";
import { projectSlice } from "store/project";
import { selectActiveKindId } from "store/project/selectors";

export const AddKindMenu = ({
anchor,
Expand All @@ -18,6 +19,8 @@ export const AddKindMenu = ({
filteredKinds: string[];
}) => {
const dispatch = useDispatch();
const activeKind = useSelector(selectActiveKindId);
const isMobile = useMobileView();
const {
onOpen: handleOpenCreateKindDialog,
onClose: handleCloseCreateKindDialog,
Expand All @@ -27,7 +30,17 @@ export const AddKindMenu = ({
const handleUnfilterKind = (kindId: string) => {
dispatch(projectSlice.actions.removeKindTabFilter({ kindId }));
dispatch(projectSlice.actions.setActiveKind({ kind: kindId }));
if (isMobile) {
dispatch(projectSlice.actions.addKindTabFilter({ kindId: activeKind }));
}
onClose();
};
const closeActiveKind = () => {
dispatch(projectSlice.actions.addKindTabFilter({ kindId: activeKind }));
};
const handleCloseCreateKindDialogAndMenu = () => {
handleCloseCreateKindDialog();
onClose();
};
return (
<>
Expand Down Expand Up @@ -57,8 +70,9 @@ export const AddKindMenu = ({
))}
</BaseMenu>
<CreateKindDialog
onClose={handleCloseCreateKindDialog}
onClose={handleCloseCreateKindDialogAndMenu}
open={isCreateKindDialogOpen}
secondaryAction={isMobile ? closeActiveKind : undefined}
/>
</>
);
Expand Down
2 changes: 2 additions & 0 deletions src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export { useHotkeys } from "./useHotkeys";
export { usePointerLocation } from "./usePointerLocation/usePointerLocation";
export { useErrorHandler } from "./useErrorHandler";
export { useUnloadConfirmation } from "./useUnloadConfirmation";
export { useBreakpointObserver } from "./useBreakpointObserver";
export { useMobileView } from "./useMobileView";

// useDefaultImage not included to encourage use of
// import {useDefaultImage, DispatchLocation} from "hooks/useDefaultImage"
1 change: 1 addition & 0 deletions src/hooks/useBreakpointObserver/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { useBreakpointObserver } from "./useBreakpointObserver";
13 changes: 13 additions & 0 deletions src/hooks/useBreakpointObserver/useBreakpointObserver.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Breakpoint, useMediaQuery, useTheme } from "@mui/material";
type BreakpointOrNull = Breakpoint | null;
export const useBreakpointObserver = () => {
const theme = useTheme();
const keys: readonly Breakpoint[] = [...theme.breakpoints.keys].reverse();
return (
keys.reduce((output: BreakpointOrNull, key: Breakpoint) => {
// eslint-disable-next-line react-hooks/rules-of-hooks
const matches = useMediaQuery(theme.breakpoints.up(key));
return !output && matches ? key : output;
}, null) || "xs"
);
};
1 change: 1 addition & 0 deletions src/hooks/useMobileView/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { useMobileView } from "./useMobileView";
15 changes: 15 additions & 0 deletions src/hooks/useMobileView/useMobileView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { useBreakpointObserver } from "hooks/useBreakpointObserver/useBreakpointObserver";
import { useEffect, useState } from "react";
import { mobileBreakpoints } from "utils/common/constants";

export const useMobileView = () => {
const breakpoint = useBreakpointObserver();
const [isMobile, setIsMobile] = useState(
mobileBreakpoints.includes(breakpoint)
);
useEffect(() => {
setIsMobile(mobileBreakpoints.includes(breakpoint));
}, [breakpoint]);

return isMobile;
};
2 changes: 2 additions & 0 deletions src/utils/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,5 @@ export const availableImageSortKeys: ImageSortKeyType[] = [
objectType: "Annotations",
},
];

export const mobileBreakpoints = ["xs", "sm"];
Loading

0 comments on commit 73b0edc

Please sign in to comment.