Skip to content

Commit

Permalink
[ENG-1751] Improve active item handling (#2367)
Browse files Browse the repository at this point in the history
base
  • Loading branch information
niikeec authored Apr 22, 2024
1 parent 959ccdf commit 745399e
Show file tree
Hide file tree
Showing 11 changed files with 249 additions and 269 deletions.
10 changes: 10 additions & 0 deletions interface/app/$libraryId/Explorer/QuickPreview/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import { Conditional } from '../ContextMenu/ConditionalItem';
import { FileThumb } from '../FilePath/Thumb';
import { SingleItemMetadata } from '../Inspector';
import { explorerStore } from '../store';
import { useExplorerViewContext } from '../View/Context';
import { ImageSlider } from './ImageSlider';
import { getQuickPreviewStore, useQuickPreviewStore } from './store';

Expand All @@ -74,6 +75,7 @@ export const QuickPreview = () => {
const { openFilePaths, openEphemeralFiles } = usePlatform();
const explorerLayoutStore = useExplorerLayoutStore();
const explorer = useExplorerContext();
const explorerView = useExplorerViewContext();
const { open, itemIndex } = useQuickPreviewStore();

const thumb = createRef<HTMLDivElement>();
Expand Down Expand Up @@ -155,6 +157,14 @@ export const QuickPreview = () => {
setShowMetadata(false);
}, [item, open]);

useEffect(() => {
if (open) explorerView.updateActiveItem(null, { updateFirstItem: true });

// "open" is excluded, as we only want this to trigger when hashes change,
// that way we don't have to manually update the active item.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [explorer.selectedItemHashes, explorerView.updateActiveItem]);

const handleMoveBetweenItems = (step: number) => {
const nextPreviewItem = items[itemIndex + step];
if (nextPreviewItem) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { createContext, useContext, type ReactNode, type RefObject } from 'react';

export interface ExplorerViewContext {
import { useActiveItem } from './useActiveItem';

export interface ExplorerViewContextProps extends ReturnType<typeof useActiveItem> {
ref: RefObject<HTMLDivElement>;
/**
* Padding to apply when scrolling to an item.
Expand All @@ -13,10 +15,10 @@ export interface ExplorerViewContext {
};
}

export const ViewContext = createContext<ExplorerViewContext | null>(null);
export const ExplorerViewContext = createContext<ExplorerViewContextProps | null>(null);

export const useExplorerViewContext = () => {
const ctx = useContext(ViewContext);
const ctx = useContext(ExplorerViewContext);

if (ctx === null) throw new Error('ViewContext.Provider not found!');

Expand Down
62 changes: 38 additions & 24 deletions interface/app/$libraryId/Explorer/View/Grid/DragSelect/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { useExplorerContext } from '../../../Context';
import { explorerStore } from '../../../store';
import { useExplorerOperatingSystem } from '../../../useExplorerOperatingSystem';
import { useExplorerViewContext } from '../../Context';
import { useKeySelection } from '../useKeySelection';
import { DragSelectContext } from './context';
import { useSelectedTargets } from './useSelectedTargets';
import { getElementIndex, SELECTABLE_DATA_ATTRIBUTE } from './util';
Expand All @@ -16,7 +15,6 @@ const CHROME_REGEX = /Chrome/;

interface Props extends PropsWithChildren {
grid: ReturnType<typeof useGrid<string, ExplorerItem | undefined>>;
onActiveItemChange: ReturnType<typeof useKeySelection>['updateActiveItem'];
}

export interface Drag {
Expand All @@ -26,11 +24,13 @@ export interface Drag {
endRow: number;
}

export const DragSelect = ({ grid, children, onActiveItemChange }: Props) => {
export const DragSelect = ({ grid, children }: Props) => {
const isChrome = CHROME_REGEX.test(navigator.userAgent);

const { explorerOperatingSystem, matchingOperatingSystem } = useExplorerOperatingSystem();

const isWindows = explorerOperatingSystem === 'windows' && matchingOperatingSystem;

const explorer = useExplorerContext();
const explorerView = useExplorerViewContext();

Expand Down Expand Up @@ -99,20 +99,20 @@ export const DragSelect = ({ grid, children, onActiveItemChange }: Props) => {

// Update active item to the first selected target(first grid item in DOM).
const target = selecto.current?.getSelectedTargets()?.[0];
const item = target && getGridItem(target)?.data;
if (item) onActiveItemChange(item, { updateFirstItem: true, setFirstItemAsChanged: true });

const item = target && getGridItem(target);
if (!item) return;

explorerView.updateActiveItem(item.id as string, {
updateFirstItem: true
});
}

function handleSelect(e: SelectoEvents['select']) {
const inputEvent = e.inputEvent as MouseEvent;

let continueSelection = false;

if (explorerOperatingSystem === 'windows') {
continueSelection = matchingOperatingSystem ? inputEvent.ctrlKey : inputEvent.metaKey;
} else {
continueSelection = inputEvent.shiftKey || inputEvent.metaKey;
}
const continueSelection =
inputEvent.shiftKey || (isWindows ? inputEvent.ctrlKey : inputEvent.metaKey);

// Handle select on mouse down
if (inputEvent.type === 'mousedown') {
Expand All @@ -130,7 +130,10 @@ export const DragSelect = ({ grid, children, onActiveItemChange }: Props) => {
};

if (!continueSelection) {
if (explorer.selectedItems.has(item.data)) {
if (
explorerOperatingSystem !== 'windows' &&
explorer.selectedItems.has(item.data)
) {
// Keep previous selection as selecto will reset it otherwise
selecto.current?.setSelectedTargets(e.beforeSelected);
} else {
Expand All @@ -140,14 +143,31 @@ export const DragSelect = ({ grid, children, onActiveItemChange }: Props) => {
]);
}

explorerView.updateActiveItem(item.id as string, { updateFirstItem: true });
return;
}

if (e.added[0]) explorer.addSelectedItem(item.data);
else explorer.removeSelectedItem(item.data);
if (explorerOperatingSystem === 'windows' && inputEvent.shiftKey) {
explorerView.handleWindowsGridShiftSelection(item.index);
return;
}

// Update active item for further keyboard selection.
onActiveItemChange(item.data, { updateFirstItem: true, setFirstItemAsChanged: true });
if (e.added[0]) {
explorer.addSelectedItem(item.data);
explorerView.updateActiveItem(item.id as string, { updateFirstItem: true });
return;
}

explorer.removeSelectedItem(item.data);

explorerView.updateActiveItem(
explorerOperatingSystem === 'windows' ? (item.id as string) : null,
{
updateFirstItem: true
}
);

return;
}

// Handle select by drag
Expand Down Expand Up @@ -557,13 +577,7 @@ export const DragSelect = ({ grid, children, onActiveItemChange }: Props) => {
throttleTime: isChrome ? 30 : 10000
}}
selectableTargets={[`[${SELECTABLE_DATA_ATTRIBUTE}]`]}
toggleContinueSelect={
explorerOperatingSystem === 'windows'
? matchingOperatingSystem
? 'ctrl'
: 'meta'
: [['shift'], ['meta']]
}
toggleContinueSelect={[['shift'], [isWindows ? 'ctrl' : 'meta']]}
hitRate={0}
onDrag={handleDrag}
onDragStart={handleDragStart}
Expand Down
Loading

0 comments on commit 745399e

Please sign in to comment.