Fix desktop long press action
After the long press action, the set onClick action was triggered as well. This caused issues like opening the manga page in the source browse page when adding the manga via a long press to the library
This commit is contained in:
71
src/base/hooks/usePress.ts
Normal file
71
src/base/hooks/usePress.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { useCallback, useRef } from 'react';
|
||||
import type {
|
||||
LongPressCallbackMeta,
|
||||
LongPressMouseHandlers,
|
||||
LongPressPointerHandlers,
|
||||
LongPressReactEvents,
|
||||
LongPressResult,
|
||||
LongPressTouchHandlers,
|
||||
} from 'use-long-press';
|
||||
// oxlint-disable-next-line no-restricted-imports
|
||||
import { useLongPress } from 'use-long-press';
|
||||
|
||||
export type UsePressResult = LongPressResult<
|
||||
(LongPressPointerHandlers | LongPressMouseHandlers | LongPressTouchHandlers) & {
|
||||
onClick: (event: React.MouseEvent | React.TouchEvent) => void;
|
||||
}
|
||||
>;
|
||||
|
||||
export const usePress = (
|
||||
options: Omit<Parameters<typeof useLongPress>[1], 'onCancel' | 'onStart'> & {
|
||||
onLongPress: NonNullable<Parameters<typeof useLongPress>[0]>;
|
||||
onPress: (event: React.MouseEvent | React.TouchEvent) => void;
|
||||
},
|
||||
): UsePressResult => {
|
||||
const { onLongPress, onPress, ...actualOptions } = options;
|
||||
|
||||
const hasLongPressRef = useRef(false);
|
||||
|
||||
const onCancel = useCallback(() => {
|
||||
if (hasLongPressRef.current) {
|
||||
hasLongPressRef.current = false;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const bind = useLongPress(
|
||||
useCallback(
|
||||
(event: LongPressReactEvents<Element>, meta: LongPressCallbackMeta<unknown>) => {
|
||||
hasLongPressRef.current = true;
|
||||
onLongPress(event, meta);
|
||||
},
|
||||
[onLongPress],
|
||||
),
|
||||
{
|
||||
...actualOptions,
|
||||
onCancel,
|
||||
onStart: onCancel,
|
||||
},
|
||||
);
|
||||
|
||||
return useCallback(
|
||||
(context?: unknown) => ({
|
||||
...bind(context),
|
||||
onClick: (event: React.MouseEvent | React.TouchEvent) => {
|
||||
if (!hasLongPressRef.current) {
|
||||
onPress(event);
|
||||
} else {
|
||||
event.preventDefault();
|
||||
}
|
||||
},
|
||||
}),
|
||||
[bind, onPress],
|
||||
);
|
||||
};
|
||||
@@ -18,7 +18,6 @@ import type { MouseEvent, TouchEvent } from 'react';
|
||||
import React, { memo, useRef } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import PopupState, { bindMenu, bindTrigger } from 'material-ui-popup-state';
|
||||
import { useLongPress } from 'use-long-press';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { CustomTooltip } from '@/base/components/CustomTooltip.tsx';
|
||||
import { getDateString } from '@/base/utils/DateHelper.ts';
|
||||
@@ -43,6 +42,7 @@ import type {
|
||||
} from '@/features/chapter/Chapter.types.ts';
|
||||
import { MediaQuery } from '@/base/utils/MediaQuery.tsx';
|
||||
import type { ChapterType } from '@/lib/graphql/generated/graphql-base.types.ts';
|
||||
import { usePress } from '@/base/hooks/usePress.ts';
|
||||
|
||||
type TChapter = ChapterIdInfo &
|
||||
ChapterMangaInfo &
|
||||
@@ -104,15 +104,18 @@ export const ChapterCard = memo((props: IProps) => {
|
||||
onSelect(chapter.id, !selected, event.shiftKey);
|
||||
};
|
||||
|
||||
const longPressBind = useLongPress((event, { context: openMenu }) => {
|
||||
if (!isSelecting && !!menuButtonRef.current) {
|
||||
handleClickOpenMenu(event, () => (openMenu as (event: Element) => void)?.(menuButtonRef.current!));
|
||||
return;
|
||||
}
|
||||
const longPressBind = usePress({
|
||||
onLongPress: (event, { context: openMenu }) => {
|
||||
if (!isSelecting && !!menuButtonRef.current) {
|
||||
handleClickOpenMenu(event, () => (openMenu as (event: Element) => void)?.(menuButtonRef.current!));
|
||||
return;
|
||||
}
|
||||
|
||||
// oxlint-disable-next-line no-param-reassign
|
||||
event.shiftKey = true;
|
||||
handleClick(event);
|
||||
// oxlint-disable-next-line no-param-reassign
|
||||
event.shiftKey = true;
|
||||
handleClick(event);
|
||||
},
|
||||
onPress: handleClick,
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -136,7 +139,6 @@ export const ChapterCard = memo((props: IProps) => {
|
||||
}}
|
||||
state={Chapters.getReaderOpenChapterLocationState(chapter, true)}
|
||||
replace={mode === 'reader'}
|
||||
onClick={(e) => handleClick(e)}
|
||||
{...longPressBind(popupState.open)}
|
||||
>
|
||||
<ListCardContent>
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import type { LongPressPointerHandlers, LongPressResult } from 'use-long-press';
|
||||
import type { PopupState } from 'material-ui-popup-state/hooks';
|
||||
import type { JSX } from 'react';
|
||||
import type { SelectableCollectionReturnType } from '@/base/collection/hooks/useSelectableCollection.ts';
|
||||
@@ -29,6 +28,7 @@ import type {
|
||||
SourceType,
|
||||
TrackRecordType,
|
||||
} from '@/lib/graphql/generated/graphql-base.types.ts';
|
||||
import type { UsePressResult } from '@/base/hooks/usePress.ts';
|
||||
|
||||
export type MangaCardMode = 'default' | 'source' | 'migrate.select.bulk' | 'migrate.select.single' | 'duplicate';
|
||||
|
||||
@@ -75,9 +75,8 @@ export interface MangaCardProps {
|
||||
export type SpecificMangaCardProps = Omit<MangaCardProps, 'manga'> &
|
||||
Pick<ReturnType<typeof useManageMangaLibraryState>, 'isInLibrary'> & {
|
||||
manga: MangaCardSpecificProps;
|
||||
longPressBind: LongPressResult<LongPressPointerHandlers>;
|
||||
longPressBind: UsePressResult;
|
||||
popupState: PopupState;
|
||||
handleClick: (event: React.MouseEvent | React.TouchEvent) => void;
|
||||
mangaLinkTo: string;
|
||||
continueReadingButton: JSX.Element;
|
||||
mangaBadges: JSX.Element;
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
import PopupState, { bindMenu } from 'material-ui-popup-state';
|
||||
import { memo, useCallback, useMemo } from 'react';
|
||||
import { useLongPress } from 'use-long-press';
|
||||
import type { SingleModeProps } from '@/features/manga/components/MangaActionMenuItems.tsx';
|
||||
import { MangaActionMenuItems } from '@/features/manga/components/MangaActionMenuItems.tsx';
|
||||
import { Menu } from '@/base/components/menu/Menu.tsx';
|
||||
@@ -32,6 +31,7 @@ import { MangaMigration } from '@/features/migration/MangaMigration.ts';
|
||||
import { MANGA_ACTION_TO_TRANSLATION } from '@/features/manga/Manga.constants.ts';
|
||||
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
|
||||
import { assertIsDefined } from '@/base/Asserts.ts';
|
||||
import { usePress } from '@/base/hooks/usePress.ts';
|
||||
|
||||
const getMangaLinkTo = (mode: MangaCardMode, mangaId: number): string => {
|
||||
switch (mode) {
|
||||
@@ -149,8 +149,8 @@ export const MangaCard = memo((props: MangaCardProps) => {
|
||||
[mode, selected, updateLibraryState, handleSelection, migrationSourceMangaId],
|
||||
);
|
||||
|
||||
const longPressBind = useLongPress(
|
||||
useCallback(
|
||||
const longPressBind = usePress({
|
||||
onLongPress: useCallback(
|
||||
(e: any, { context }: any) => {
|
||||
// oxlint-disable-next-line no-param-reassign
|
||||
e.shiftKey = true;
|
||||
@@ -158,7 +158,8 @@ export const MangaCard = memo((props: MangaCardProps) => {
|
||||
},
|
||||
[handleClick],
|
||||
),
|
||||
);
|
||||
onPress: handleClick,
|
||||
});
|
||||
|
||||
const MangaCardComponent = useMemo(
|
||||
() => (gridLayout === GridLayout.List ? MangaListCard : MangaGridCard),
|
||||
@@ -173,7 +174,6 @@ export const MangaCard = memo((props: MangaCardProps) => {
|
||||
{...props}
|
||||
longPressBind={longPressBind}
|
||||
popupState={popupState}
|
||||
handleClick={handleClick}
|
||||
mangaLinkTo={mangaLinkTo}
|
||||
isInLibrary={isInLibrary}
|
||||
inLibraryIndicator={inLibraryIndicator}
|
||||
|
||||
@@ -45,7 +45,6 @@ export const MangaGridCard = memo(
|
||||
manga,
|
||||
longPressBind,
|
||||
popupState,
|
||||
handleClick,
|
||||
mangaLinkTo,
|
||||
selected,
|
||||
inLibraryIndicator,
|
||||
@@ -65,7 +64,6 @@ export const MangaGridCard = memo(
|
||||
<Link
|
||||
component={RouterLink}
|
||||
{...longPressBind(() => popupState.open(optionButtonRef.current))}
|
||||
onClick={handleClick}
|
||||
to={mangaLinkTo}
|
||||
state={Mangas.createLocationState(manga, mode)}
|
||||
onContextMenu={preventMobileContextMenu}
|
||||
|
||||
@@ -26,7 +26,6 @@ export const MangaListCard = memo(
|
||||
manga,
|
||||
longPressBind,
|
||||
popupState,
|
||||
handleClick,
|
||||
mangaLinkTo,
|
||||
selected,
|
||||
inLibraryIndicator,
|
||||
@@ -48,7 +47,6 @@ export const MangaListCard = memo(
|
||||
component={RouterLink}
|
||||
to={mangaLinkTo}
|
||||
state={Mangas.createLocationState(manga, mode)}
|
||||
onClick={handleClick}
|
||||
{...longPressBind(() => popupState.open(optionButtonRef.current))}
|
||||
onContextMenu={preventMobileContextMenu}
|
||||
sx={{
|
||||
|
||||
Reference in New Issue
Block a user