Skip to content

Commit

Permalink
fix: define container for drag selection
Browse files Browse the repository at this point in the history
  • Loading branch information
pyphilia committed Sep 27, 2024
1 parent 5d2c0b0 commit 4766945
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 64 deletions.
48 changes: 29 additions & 19 deletions src/components/item/FolderContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ type Props = {
canWrite?: boolean;
};

const CONTAINER_ID = 'items-container-id';

const Content = ({
item,
searchText,
Expand All @@ -60,7 +62,7 @@ const Content = ({
const { itemTypes } = useFilterItemsContext();
const { selectedIds, clearSelection, toggleSelection } =
useSelectionContext();
const DragSelection = useDragSelection();
const DragSelection = useDragSelection({ containerId: CONTAINER_ID });

if (mode === ItemLayoutMode.Map) {
return (
Expand All @@ -73,24 +75,32 @@ const Content = ({
if (items?.length) {
return (
<>
<ItemsTable
selectedIds={selectedIds}
enableMoveInBetween={sortBy === SortingOptionsForFolder.Order}
id={buildItemsTableId(item.id)}
items={items ?? []}
onCardClick={toggleSelection}
onMove={clearSelection}
/>
{Boolean(canWrite && !searchText && !itemTypes?.length) && (
<Stack alignItems="center" mb={2}>
<NewItemButton
type="icon"
key="newButton"
// add new items at the end of the list
previousItemId={items ? items[items.length - 1]?.id : undefined}
/>
</Stack>
)}
<Stack
// this is a hack to allow selection dragging from margin
mx={-100}
px={100}
height="100%"
id={CONTAINER_ID}
>
<ItemsTable
selectedIds={selectedIds}
enableMoveInBetween={sortBy === SortingOptionsForFolder.Order}
id={buildItemsTableId(item.id)}
items={items ?? []}
onCardClick={toggleSelection}
onMove={clearSelection}
/>
{Boolean(canWrite && !searchText && !itemTypes?.length) && (
<Stack alignItems="center" mb={2}>
<NewItemButton
type="icon"
key="newButton"
// add new items at the end of the list
previousItemId={items ? items[items.length - 1]?.id : undefined}
/>
</Stack>
)}
</Stack>
{DragSelection}
</>
);
Expand Down
11 changes: 8 additions & 3 deletions src/components/main/list/ItemsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,16 @@ const ItemsTable = ({
return;
}

// silent error, happens when you want to cancel the operation
if (movedItem.id === targetItem.id) {
console.error('cannot move target into itself');
return;
}

// cannot move item into itself, or target cannot be part of selection if moving selection
if (
movedItem.id === targetItem.id ||
(selectedIds.includes(movedItem?.id) &&
selectedIds.includes(targetItem.id))
selectedIds.includes(movedItem?.id) &&
selectedIds.includes(targetItem.id)
) {
toast.error(translateMessage(FAILURE_MESSAGES.INVALID_MOVE_TARGET));
return;
Expand Down
6 changes: 5 additions & 1 deletion src/components/main/list/SelectionContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {
useState,
} from 'react';

import { Stack } from '@mui/material';

type SelectionContextValue = {
selectedIds: string[];
toggleSelection: (id: string) => void;
Expand Down Expand Up @@ -74,7 +76,9 @@ export const SelectionContextProvider = ({

return (
<SelectionContext.Provider value={value}>
<div ref={elementsContainerRef}>{children}</div>
<Stack height="100%" ref={elementsContainerRef}>
{children}
</Stack>
</SelectionContext.Provider>
);
};
Expand Down
13 changes: 11 additions & 2 deletions src/components/main/list/useDragSelection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ import { useSelectionContext } from './SelectionContext';

export const useDragSelection = ({
elementClass = ITEM_CARD_CLASS,
} = {}): JSX.Element => {
containerId,
}: {
containerId: string;
elementClass?: string;
}): JSX.Element => {
const { addToSelection, clearSelection } = useSelectionContext();
const [boundingBox, setBoundingBox] = useState<null | {
top: number;
Expand Down Expand Up @@ -52,8 +56,13 @@ export const useDragSelection = ({
);
},
shouldStartSelecting: (e) => {
// does not trigger drag selection if mousedown on card
if (e instanceof HTMLElement || e instanceof SVGElement) {
// does not trigger if click is outside of container
if (!e.closest(`#${containerId}`)) {
return false;
}

// does not trigger drag selection if mousedown on card
return !e?.closest(`.${elementClass}`);
}
return true;
Expand Down
25 changes: 18 additions & 7 deletions src/components/pages/PageWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,25 @@ const PageWrapper = ({
<Helmet>
<title>{title}</title>
</Helmet>
<Container id={id} sx={{ my: 2 }}>
<Stack mb={2} direction="row" justifyContent="space-between" spacing={1}>
<Typography variant="h2" component="h1" sx={{ wordWrap: 'break-word' }}>
{title}
</Typography>
{options}
<Container id={id} sx={{ pt: 1, height: '100%' }}>
<Stack height="100%">
<Stack
mb={2}
direction="row"
justifyContent="space-between"
spacing={1}
>
<Typography
variant="h2"
component="h1"
sx={{ wordWrap: 'break-word' }}
>
{title}
</Typography>
{options}
</Stack>
{children}
</Stack>
{children}
</Container>
</>
);
Expand Down
67 changes: 39 additions & 28 deletions src/components/pages/RecycledItemsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import { useSorting, useTranslatedSortingOptions } from '../table/useSorting';
import PageWrapper from './PageWrapper';
import RecycleBinToolbar from './recycleBin/RecycleBinSelectionToolbar';

const CONTAINER_ID = 'recycle-items-container';

const RecycledItemsScreenContent = ({
searchText,
}: {
Expand All @@ -52,14 +54,14 @@ const RecycledItemsScreenContent = ({
?.sort(sortFn);
const { selectedIds, toggleSelection } = useSelectionContext();

const DragSelection = useDragSelection();
const DragSelection = useDragSelection({ containerId: CONTAINER_ID });

// render this when there is data from the query
if (recycledItems?.length) {
const hasSelection = selectedIds.length && filteredData?.length;
return (
<>
<Stack gap={1}>
<Stack gap={1} height="100%">
<Stack
alignItems="space-between"
direction="column"
Expand Down Expand Up @@ -91,32 +93,41 @@ const RecycledItemsScreenContent = ({
</Stack>
)}
</Stack>
{
// render the filtered data and when it is empty display that nothing matches the search
filteredData?.length ? (
filteredData.map((item) => (
<ItemCard
item={item}
onThumbnailClick={() => toggleSelection(item.id)}
isSelected={selectedIds.includes(item.id)}
showThumbnail={false}
allowNavigation={false}
footer={
<Stack justifyContent="right" direction="row">
<RestoreButton itemIds={[item.id]} />
<DeleteButton items={[item]} />
</Stack>
}
/>
))
) : (
<Alert severity="info">
{translateBuilder(BUILDER.TRASH_NO_ITEM_SEARCH, {
search: searchText,
})}
</Alert>
)
}
<Stack
// this is a hack to allow selection dragging from margin
mx={-100}
px={100}
id={CONTAINER_ID}
gap={1}
height="100%"
>
{
// render the filtered data and when it is empty display that nothing matches the search
filteredData?.length ? (
filteredData.map((item) => (
<ItemCard
item={item}
onThumbnailClick={() => toggleSelection(item.id)}
isSelected={selectedIds.includes(item.id)}
showThumbnail={false}
allowNavigation={false}
footer={
<Stack justifyContent="right" direction="row">
<RestoreButton itemIds={[item.id]} />
<DeleteButton items={[item]} />
</Stack>
}
/>
))
) : (
<Alert severity="info">
{translateBuilder(BUILDER.TRASH_NO_ITEM_SEARCH, {
search: searchText,
})}
</Alert>
)
}
</Stack>
</Stack>
{DragSelection}
</>
Expand Down
16 changes: 12 additions & 4 deletions src/components/pages/home/HomeScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ import NoItemFilters from '../NoItemFilters';
import PageWrapper from '../PageWrapper';
import HomeSelectionToolbar from './HomeSelectionToolbar';

const CONTAINER_ID = 'home-items-container';

const HomeScreenContent = ({ searchText }: { searchText: string }) => {
const { t: translateBuilder } = useBuilderTranslation();
const { t: translateEnums } = useEnumsTranslation();
Expand Down Expand Up @@ -75,7 +77,7 @@ const HomeScreenContent = ({ searchText }: { searchText: string }) => {
{ pageSize: ITEM_PAGE_SIZE },
);

const DragSelection = useDragSelection();
const DragSelection = useDragSelection({ containerId: CONTAINER_ID });

const onShowOnlyMeChange: ShowOnlyMeChangeType = (checked) => {
setShowOnlyMe(checked);
Expand Down Expand Up @@ -105,7 +107,13 @@ const HomeScreenContent = ({ searchText }: { searchText: string }) => {
? data.pages.map(({ data: d }) => d.length).reduce((a, b) => a + b, 0)
: 0;
content = (
<>
<Stack
// this is a hack to allow selection dragging from margin
mx={-100}
px={100}
id={CONTAINER_ID}
height="100%"
>
<ItemsTable
canMove={!searchText}
id={ACCESSIBLE_ITEMS_TABLE_ID}
Expand All @@ -128,7 +136,7 @@ const HomeScreenContent = ({ searchText }: { searchText: string }) => {
<NewItemButton type="icon" />
</Stack>
)}
</>
</Stack>
);
} else if (itemTypes.length || searchText) {
content = <NoItemFilters searchText={searchText} />;
Expand Down Expand Up @@ -182,7 +190,7 @@ const HomeScreenContent = ({ searchText }: { searchText: string }) => {
</Stack>
)}
</Stack>
<Stack>
<Stack height="100%">
{content}
{data && isFetching && (
<Box sx={{ width: '100%' }}>
Expand Down

0 comments on commit 4766945

Please sign in to comment.