feat(ui): update useGlobalModifiers to store each key independently

This reduces rerenders when the user presses a modifier key.
This commit is contained in:
psychedelicious 2024-01-01 15:55:11 +11:00 committed by Kent Keirsey
parent 7e2eeec1f3
commit 5c3dd62ae0
5 changed files with 30 additions and 39 deletions

View File

@ -1,6 +1,6 @@
import { forwardRef, NumberInput as ChakraNumberInput } from '@chakra-ui/react';
import { useStore } from '@nanostores/react';
import { $modifiers } from 'common/hooks/useGlobalModifiers';
import { $shift } from 'common/hooks/useGlobalModifiers';
import { roundToMultiple } from 'common/util/roundDownToMultiple';
import { stopPastePropagation } from 'common/util/stopPastePropagation';
import { clamp } from 'lodash-es';
@ -29,10 +29,10 @@ export const InvNumberInput = memo(
const [valueAsString, setValueAsString] = useState<string>(String(value));
const [valueAsNumber, setValueAsNumber] = useState<number>(value);
const modifiers = useStore($modifiers);
const shift = useStore($shift);
const step = useMemo(
() => (modifiers.shift ? _fineStep ?? _step : _step),
[modifiers.shift, _fineStep, _step]
() => (shift ? _fineStep ?? _step : _step),
[shift, _fineStep, _step]
);
const isInteger = useMemo(
() => Number.isInteger(_step) && Number.isInteger(_fineStep ?? 1),

View File

@ -9,7 +9,7 @@ import {
import { useStore } from '@nanostores/react';
import type { InvFormattedMark } from 'common/components/InvSlider/types';
import { InvTooltip } from 'common/components/InvTooltip/InvTooltip';
import { $modifiers } from 'common/hooks/useGlobalModifiers';
import { $shift } from 'common/hooks/useGlobalModifiers';
import { AnimatePresence } from 'framer-motion';
import { memo, useCallback, useMemo, useState } from 'react';
@ -35,10 +35,10 @@ export const InvRangeSlider = memo(
const [isMouseOverSlider, setIsMouseOverSlider] = useState(false);
const [isChanging, setIsChanging] = useState(false);
const modifiers = useStore($modifiers);
const shift = useStore($shift);
const step = useMemo(
() => (modifiers.shift ? _fineStep ?? _step : _step),
[modifiers.shift, _fineStep, _step]
() => (shift ? _fineStep ?? _step : _step),
[shift, _fineStep, _step]
);
const controlProps = useFormControl({});

View File

@ -8,7 +8,7 @@ import {
import { useStore } from '@nanostores/react';
import { InvNumberInput } from 'common/components/InvNumberInput/InvNumberInput';
import { InvTooltip } from 'common/components/InvTooltip/InvTooltip';
import { $modifiers } from 'common/hooks/useGlobalModifiers';
import { $shift } from 'common/hooks/useGlobalModifiers';
import { AnimatePresence } from 'framer-motion';
import { memo, useCallback, useMemo, useState } from 'react';
@ -36,10 +36,10 @@ export const InvSlider = memo((props: InvSliderProps) => {
const [isMouseOverSlider, setIsMouseOverSlider] = useState(false);
const [isChanging, setIsChanging] = useState(false);
const modifiers = useStore($modifiers);
const shift = useStore($shift);
const step = useMemo(
() => (modifiers.shift ? _fineStep ?? _step : _step),
[modifiers.shift, _fineStep, _step]
() => (shift ? _fineStep ?? _step : _step),
[shift, _fineStep, _step]
);
const controlProps = useFormControl({});

View File

@ -1,27 +1,18 @@
import { atom, map } from 'nanostores';
import { atom } from 'nanostores';
import { useCallback, useEffect } from 'react';
export type Modifiers = {
shift: boolean;
ctrl: boolean;
meta: boolean;
alt: boolean;
};
export const $modifiers = map<Modifiers>({
shift: false,
ctrl: false,
meta: false,
alt: false,
});
export const $shift = atom(false);
export const $ctrl = atom(false);
export const $meta = atom(false);
export const $alt = atom(false);
const $subscribers = atom(0);
const listener = (e: KeyboardEvent) => {
$modifiers.setKey('shift', e.shiftKey);
$modifiers.setKey('ctrl', e.ctrlKey);
$modifiers.setKey('alt', e.altKey);
$modifiers.setKey('meta', e.metaKey);
$shift.set(e.shiftKey);
$ctrl.set(e.ctrlKey);
$alt.set(e.altKey);
$meta.set(e.metaKey);
};
export const useGlobalModifiersInit = () => {
@ -46,16 +37,16 @@ export const useGlobalModifiersInit = () => {
export const useGlobalModifiersSetters = () => {
const setShift = useCallback((shift: boolean) => {
$modifiers.setKey('shift', shift);
$shift.set(shift);
}, []);
const setCtrl = useCallback((shift: boolean) => {
$modifiers.setKey('ctrl', shift);
const setCtrl = useCallback((ctrl: boolean) => {
$ctrl.set(ctrl);
}, []);
const setAlt = useCallback((shift: boolean) => {
$modifiers.setKey('alt', shift);
const setAlt = useCallback((alt: boolean) => {
$alt.set(alt);
}, []);
const setMeta = useCallback((shift: boolean) => {
$modifiers.setKey('meta', shift);
const setMeta = useCallback((meta: boolean) => {
$meta.set(meta);
}, []);
return { setShift, setCtrl, setAlt, setMeta };
};

View File

@ -6,7 +6,7 @@ import { useAppDispatch } from 'app/store/storeHooks';
import IAIDndImage from 'common/components/IAIDndImage';
import IAIDndImageIcon from 'common/components/IAIDndImageIcon';
import IAIFillSkeleton from 'common/components/IAIFillSkeleton';
import { $modifiers } from 'common/hooks/useGlobalModifiers';
import { $shift } from 'common/hooks/useGlobalModifiers';
import { imagesToDeleteSelected } from 'features/deleteImageModal/store/slice';
import type {
ImageDraggableData,
@ -42,7 +42,7 @@ const GalleryImage = (props: HoverableImageProps) => {
const dispatch = useAppDispatch();
const { imageName, virtuosoContext } = props;
const { currentData: imageDTO } = useGetImageDTOQuery(imageName);
const { shift } = useStore($modifiers);
const shift = useStore($shift);
const { t } = useTranslation();
const { handleClick, isSelected, selection, selectionCount } =