From bda95dbe5f0485c2f4652cf0086df6bcc87833bc Mon Sep 17 00:00:00 2001 From: Tomas Dvorak Date: Fri, 18 Sep 2026 22:06:20 +0200 Subject: [PATCH] feat(listview): clear selection on empty-space click (#3223) Clicks landing outside any row (below the last row, on padding) now deselect all items; rows carry a data-fm-row marker so in-row clicks stay unaffected. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../Explorer/ListView/ListBody.tsx | 56 ++++++++++++------- .../FileManager/Explorer/ListView/Row.tsx | 1 + 2 files changed, 37 insertions(+), 20 deletions(-) diff --git a/frontend/src/component/FileManager/Explorer/ListView/ListBody.tsx b/frontend/src/component/FileManager/Explorer/ListView/ListBody.tsx index 09382fbb..fa0f1911 100644 --- a/frontend/src/component/FileManager/Explorer/ListView/ListBody.tsx +++ b/frontend/src/component/FileManager/Explorer/ListView/ListBody.tsx @@ -1,6 +1,8 @@ -import { useContext, useMemo } from "react"; +import { Box } from "@mui/material"; +import { useCallback, useContext, useMemo } from "react"; import { Virtuoso } from "react-virtuoso"; -import { useAppSelector } from "../../../../redux/hooks.ts"; +import { useAppDispatch, useAppSelector } from "../../../../redux/hooks.ts"; +import { setSelected } from "../../../../redux/fileManagerSlice.ts"; import DndWrappedFile from "../../Dnd/DndWrappedFile.tsx"; import { FmIndexContext } from "../../FmIndexContext.tsx"; import { FmFile, loadingPlaceHolderNumb } from "../GridView/GridView.tsx"; @@ -14,6 +16,7 @@ export interface ListBodyProps { const ListBody = ({ columns }: ListBodyProps) => { const fmIndex = useContext(FmIndexContext); + const dispatch = useAppDispatch(); const files = useAppSelector((state) => state.fileManager[fmIndex].list?.files); const mixedType = useAppSelector((state) => state.fileManager[fmIndex].list?.mixed_type); const pagination = useAppSelector((state) => state.fileManager[fmIndex].list?.pagination); @@ -46,25 +49,38 @@ const ListBody = ({ columns }: ListBodyProps) => { return list; }, [files, mixedType, pagination, search_params]); + // Clicking empty space below/around rows clears the selection (#3223); + // row clicks are excluded via the data-fm-row marker. + const onBackgroundClick = useCallback( + (e: React.MouseEvent) => { + if (!(e.target as HTMLElement).closest("[data-fm-row]")) { + dispatch(setSelected({ index: fmIndex, value: [] })); + } + }, + [dispatch, fmIndex], + ); + return ( - ( - - )} - /> + + ( + + )} + /> + ); }; diff --git a/frontend/src/component/FileManager/Explorer/ListView/Row.tsx b/frontend/src/component/FileManager/Explorer/ListView/Row.tsx index 4a1b9668..0f658fc9 100644 --- a/frontend/src/component/FileManager/Explorer/ListView/Row.tsx +++ b/frontend/src/component/FileManager/Explorer/ListView/Row.tsx @@ -91,6 +91,7 @@ const Row = memo((props: FileBlockProps) => { return (