[ENG-1745] Mouse wheel resize (#2366)

* Resize layout items with mouse wheel

icon/item size using mouse wheel

Update useMouseItemResize.ts

Update useMouseItemResize.ts

* improve comment

* fb

* Update useMouseItemResize.ts

* Update IconSize.tsx
This commit is contained in:
ameer2468 2024-04-20 02:18:54 +03:00 committed by GitHub
parent 5624054f1e
commit f97a761346
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 101 additions and 17 deletions

View file

@ -15,8 +15,8 @@ export const IconSize = () => {
const explorer = useExplorerContext();
const settings = explorer.useSettingsSnapshot();
const defaultValue = useMemo(
() => sizes.findIndex((size) => size[0] === settings.listViewIconSize),
const value = useMemo(
() => sizes.indexMap.get(settings.listViewIconSize),
[settings.listViewIconSize]
);
@ -25,11 +25,11 @@ export const IconSize = () => {
<Subheading>{t('icon_size')}</Subheading>
<Slider
step={1}
max={sizes.length - 1}
defaultValue={[defaultValue]}
max={sizes.sizeMap.size - 1}
value={[value ?? 0]}
onValueChange={([value]) => {
const size = value !== undefined && sizes[value];
if (size) explorer.settingsStore.listViewIconSize = size[0];
const size = value !== undefined && sizes.sizeMap.get(value);
if (size) explorer.settingsStore.listViewIconSize = size;
}}
/>
</div>

View file

@ -16,7 +16,7 @@ export const TextSize = () => {
const settings = explorer.useSettingsSnapshot();
const defaultValue = useMemo(
() => sizes.findIndex((size) => size[0] === settings.listViewTextSize),
() => sizes.indexMap.get(settings.listViewTextSize),
[settings.listViewTextSize]
);
@ -25,11 +25,11 @@ export const TextSize = () => {
<Subheading>{t('text_size')}</Subheading>
<Slider
step={1}
max={sizes.length - 1}
defaultValue={[defaultValue]}
max={sizes.sizeMap.size - 1}
defaultValue={[defaultValue ?? 0]}
onValueChange={([value]) => {
const size = value !== undefined && sizes[value];
if (size) explorer.settingsStore.listViewTextSize = size[0];
const size = value !== undefined && sizes.sizeMap.get(value);
if (size) explorer.settingsStore.listViewTextSize = size;
}}
/>
</div>

View file

@ -1,3 +1,18 @@
export function getSizes<T extends { [key: string]: number }>(sizes: T) {
return (Object.entries(sizes) as [keyof T, T[keyof T]][]).sort((a, b) => a[1] - b[1]);
const sizesArr = (Object.entries(sizes) as [keyof T, T[keyof T]][]).sort((a, b) => a[1] - b[1]);
// Map fo size to index
const indexMap = new Map<keyof T, number>();
// Map of index to size
const sizeMap = new Map<number, keyof T>();
for (let i = 0; i < sizesArr.length; i++) {
const size = sizesArr[i];
if (!size) continue;
indexMap.set(size[0], i);
sizeMap.set(i, size[0]);
}
return { indexMap, sizeMap };
}

View file

@ -108,7 +108,7 @@ export default () => {
onValueChange={(value) => {
explorer.settingsStore.gridItemSize = value[0] || 100;
}}
defaultValue={[settings.gridItemSize]}
value={[settings.gridItemSize]}
max={200}
step={10}
min={60}

View file

@ -10,7 +10,7 @@ import {
} from '@sd/client';
import { dialogManager } from '@sd/ui';
import { Loader } from '~/components';
import { useKeyMatcher, useShortcut } from '~/hooks';
import { useKeyMatcher, useMouseItemResize, useShortcut } from '~/hooks';
import { useRoutingContext } from '~/RoutingContext';
import { isNonEmpty } from '~/util';
@ -139,6 +139,9 @@ export const View = ({ emptyNotice, ...contextProps }: ExplorerViewProps) => {
return () => element.removeEventListener('wheel', handleWheel);
}, [explorer.scrollRef, drag?.type]);
// Handle resizing of items in the Explorer grid and list view using the mouse wheel
useMouseItemResize();
if (!explorer.layouts[layoutMode]) return null;
return (

View file

@ -18,6 +18,9 @@ export * from './useIsLocationIndexing';
export * from './useIsTextTruncated';
export * from './useKeyMatcher';
export * from './useLocale';
export * from './useMouseItemResize';
export * from './usePrefersReducedMotion';
export * from './useRandomInterval';
export * from './useRedirectToNewLocation';
export * from './useRouteTitle';
export * from './useShortcut';
@ -25,8 +28,6 @@ export * from './useShowControls';
export * from './useTheme';
export * from './useWindowSize';
export * from './useWindowState';
export * from './useZodParams';
export * from './useZodRouteParams';
export * from './useZodSearchParams';
export * from './usePrefersReducedMotion';
export * from './useRandomInterval';
export * from './useZodParams';

View file

@ -0,0 +1,65 @@
import { useCallback, useEffect } from 'react';
import { useExplorerContext } from '~/app/$libraryId/Explorer/Context';
import { LIST_VIEW_ICON_SIZES } from '~/app/$libraryId/Explorer/View/ListView/useTable';
import { useOperatingSystem } from './useOperatingSystem';
import { getSizes } from '~/app/$libraryId/Explorer/OptionsPanel/ListView/util';
/**
* Hook that allows resizing of items in the Explorer views for GRID and LIST only - using the mouse wheel.
*/
export const useMouseItemResize = () => {
const os = useOperatingSystem();
const explorer = useExplorerContext();
const { layoutMode } = explorer.useSettingsSnapshot();
const handleWheel = useCallback(
(e: WheelEvent) => {
const isList = layoutMode === 'list';
const deltaYModifier = isList ? Math.sign(e.deltaY) : e.deltaY / 10; // Sensitivity adjustment
const newSize =
Number(
isList
? explorer.settingsStore.listViewIconSize
: explorer.settingsStore.gridItemSize
) + deltaYModifier;
const minSize = isList ? 0 : 60;
const maxSize = isList ? 2 : 200;
const clampedSize = Math.max(minSize, Math.min(maxSize, newSize));
if (isList) {
const listSizes = getSizes(LIST_VIEW_ICON_SIZES);
explorer.settingsStore.listViewIconSize = listSizes.sizeMap.get(clampedSize) ?? "0"
} else if (layoutMode === 'grid') {
explorer.settingsStore.gridItemSize = Number(clampedSize.toFixed(0));
}
},
[explorer.settingsStore, layoutMode]
);
useEffect(() => {
if (os !== 'windows') return;
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === 'Control') {
document.addEventListener('wheel', handleWheel);
}
};
const handleKeyUp = (e: KeyboardEvent) => {
if (e.key === 'Control') {
document.removeEventListener('wheel', handleWheel);
}
};
document.addEventListener('keydown', handleKeyDown);
document.addEventListener('keyup', handleKeyUp);
return () => {
document.removeEventListener('keydown', handleKeyDown);
document.removeEventListener('keyup', handleKeyUp);
};
}, [os, handleWheel]);
};