From 3e903fc6bc6897d3b26dfa18d96b04931d94cdea Mon Sep 17 00:00:00 2001 From: Athou Date: Mon, 26 Jun 2023 20:04:51 +0200 Subject: [PATCH] use a single call to useContextMenu as recommended in the docs --- commafeed-client/src/app/constants.ts | 1 + commafeed-client/src/app/utils.ts | 11 +++---- .../src/components/content/FeedEntries.tsx | 29 ++++++++++++---- .../src/components/content/FeedEntry.tsx | 7 ++-- .../content/FeedEntryContextMenu.tsx | 33 ++----------------- 5 files changed, 35 insertions(+), 46 deletions(-) diff --git a/commafeed-client/src/app/constants.ts b/commafeed-client/src/app/constants.ts index 9fa9df8a..0eaf7fd1 100644 --- a/commafeed-client/src/app/constants.ts +++ b/commafeed-client/src/app/constants.ts @@ -95,6 +95,7 @@ export const Constants = { }, dom: { entryId: (entry: Entry) => `entry-id-${entry.id}`, + entryContextMenuId: (entry: Entry) => entry.id, }, browserExtensionUrl: "https://github.com/Athou/commafeed-browser-extension", bitcoinWalletAddress: "1dymfUxqCWpyD7a6rQSqNy4rLVDBsAr5e", diff --git a/commafeed-client/src/app/utils.ts b/commafeed-client/src/app/utils.ts index 09ad0c16..3585ac60 100644 --- a/commafeed-client/src/app/utils.ts +++ b/commafeed-client/src/app/utils.ts @@ -30,17 +30,16 @@ export const calculatePlaceholderSize = ({ width, height, maxWidth }: { width?: export const scrollToWithCallback = ({ options, onScrollEnded }: { options: ScrollToOptions; onScrollEnded: () => void }) => { const offset = (options.top ?? 0).toFixed() - const onScroll = () => { + const onScroll = throttle(100, () => { if (window.scrollY.toFixed() === offset) { - window.removeEventListener("scroll", throttleListener) + window.removeEventListener("scroll", onScroll) onScrollEnded() } - } - const throttleListener = throttle(100, onScroll) - window.addEventListener("scroll", throttleListener) + }) + window.addEventListener("scroll", onScroll) // scrollTo does not trigger if there's nothing to do, trigger it manually - throttleListener() + onScroll() window.scrollTo(options) } diff --git a/commafeed-client/src/components/content/FeedEntries.tsx b/commafeed-client/src/components/content/FeedEntries.tsx index 53e91703..2d8a02ec 100644 --- a/commafeed-client/src/components/content/FeedEntries.tsx +++ b/commafeed-client/src/components/content/FeedEntries.tsx @@ -20,6 +20,7 @@ import { useBrowserExtension } from "hooks/useBrowserExtension" import { useMousetrap } from "hooks/useMousetrap" import { useViewMode } from "hooks/useViewMode" import { useEffect } from "react" +import { useContextMenu } from "react-contexify" import InfiniteScroll from "react-infinite-scroller" import { throttle } from "throttle-debounce" import { FeedEntry } from "./FeedEntry" @@ -59,6 +60,15 @@ export function FeedEntries() { } } + const contextMenu = useContextMenu() + const headerRightClicked = (entry: ExpendableEntry, event: React.MouseEvent) => { + event.preventDefault() + contextMenu.show({ + id: Constants.dom.entryContextMenuId(entry), + event, + }) + } + const bodyClicked = (entry: ExpendableEntry) => { if (viewMode !== "expanded") return dispatch( @@ -73,8 +83,15 @@ export function FeedEntries() { const swipedRight = (entry: ExpendableEntry) => dispatch(markEntry({ entry, read: !entry.read })) + // close context menu on scroll useEffect(() => { - const listener = () => { + const listener = throttle(100, () => contextMenu.hideAll()) + window.addEventListener("scroll", listener) + return () => window.removeEventListener("scroll", listener) + }, [contextMenu]) + + useEffect(() => { + const listener = throttle(100, () => { if (viewMode !== "expanded") return if (scrollingToEntry) return @@ -96,11 +113,10 @@ export function FeedEntries() { }) ) } - } - const throttledListener = throttle(100, listener) - window.addEventListener("scroll", throttledListener) - return () => window.removeEventListener("scroll", throttledListener) - }, [dispatch, entries, viewMode, scrollMarks, scrollingToEntry]) + }) + window.addEventListener("scroll", listener) + return () => window.removeEventListener("scroll", listener) + }, [dispatch, contextMenu, entries, viewMode, scrollMarks, scrollingToEntry]) useMousetrap("r", () => dispatch(reloadEntries())) useMousetrap("j", () => @@ -278,6 +294,7 @@ export function FeedEntries() { showSelectionIndicator={entry.id === selectedEntryId && (!entry.expanded || viewMode === "expanded")} maxWidth={sidebarVisible ? Constants.layout.entryMaxWidth : undefined} onHeaderClick={event => headerClicked(entry, event)} + onHeaderRightClick={event => headerRightClicked(entry, event)} onBodyClick={() => bodyClicked(entry)} onSwipedRight={() => swipedRight(entry)} /> diff --git a/commafeed-client/src/components/content/FeedEntry.tsx b/commafeed-client/src/components/content/FeedEntry.tsx index 19a942b0..05d6f020 100644 --- a/commafeed-client/src/components/content/FeedEntry.tsx +++ b/commafeed-client/src/components/content/FeedEntry.tsx @@ -7,7 +7,7 @@ import React from "react" import { useSwipeable } from "react-swipeable" import { FeedEntryBody } from "./FeedEntryBody" import { FeedEntryCompactHeader } from "./FeedEntryCompactHeader" -import { FeedEntryContextMenu, useFeedEntryContextMenu } from "./FeedEntryContextMenu" +import { FeedEntryContextMenu } from "./FeedEntryContextMenu" import { FeedEntryFooter } from "./FeedEntryFooter" import { FeedEntryHeader } from "./FeedEntryHeader" @@ -18,6 +18,7 @@ interface FeedEntryProps { showSelectionIndicator: boolean maxWidth?: number onHeaderClick: (e: React.MouseEvent) => void + onHeaderRightClick: (e: React.MouseEvent) => void onBodyClick: (e: React.MouseEvent) => void onSwipedRight: () => void } @@ -90,8 +91,6 @@ export function FeedEntry(props: FeedEntryProps) { onSwipedRight: props.onSwipedRight, }) - const { onContextMenu } = useFeedEntryContextMenu(props.entry) - let paddingX: MantineNumberSize = "xs" if (viewMode === "title" || viewMode === "cozy") paddingX = 6 @@ -129,7 +128,7 @@ export function FeedEntry(props: FeedEntryProps) { rel="noreferrer" onClick={props.onHeaderClick} onAuxClick={props.onHeaderClick} - onContextMenu={onContextMenu} + onContextMenu={props.onHeaderRightClick} > {compactHeader && } diff --git a/commafeed-client/src/components/content/FeedEntryContextMenu.tsx b/commafeed-client/src/components/content/FeedEntryContextMenu.tsx index 2991d1a8..aa2eb129 100644 --- a/commafeed-client/src/components/content/FeedEntryContextMenu.tsx +++ b/commafeed-client/src/components/content/FeedEntryContextMenu.tsx @@ -1,15 +1,14 @@ import { Trans } from "@lingui/macro" import { createStyles, Group } from "@mantine/core" +import { Constants } from "app/constants" import { markEntriesUpToEntry, markEntry, starEntry } from "app/slices/entries" import { redirectToFeed } from "app/slices/redirect" import { useAppDispatch, useAppSelector } from "app/store" import { Entry } from "app/types" import { truncate } from "app/utils" import { useBrowserExtension } from "hooks/useBrowserExtension" -import { useEffect } from "react" -import { Item, Menu, Separator, useContextMenu } from "react-contexify" +import { Item, Menu, Separator } from "react-contexify" import { TbArrowBarToDown, TbExternalLink, TbEyeCheck, TbEyeOff, TbRss, TbStar, TbStarOff } from "react-icons/tb" -import { throttle } from "throttle-debounce" interface FeedEntryContextMenuProps { entry: Entry @@ -28,8 +27,6 @@ const useStyles = createStyles(theme => ({ }, })) -const menuId = (entry: Entry) => entry.id - export function FeedEntryContextMenu(props: FeedEntryContextMenuProps) { const { classes, theme } = useStyles() const sourceType = useAppSelector(state => state.entries.source.type) @@ -37,7 +34,7 @@ export function FeedEntryContextMenu(props: FeedEntryContextMenuProps) { const { openLinkInBackgroundTab } = useBrowserExtension() return ( - + { window.open(props.entry.url, "_blank", "noreferrer") @@ -101,27 +98,3 @@ export function FeedEntryContextMenu(props: FeedEntryContextMenuProps) { ) } - -export function useFeedEntryContextMenu(entry: Entry) { - const contextMenu = useContextMenu({ - id: menuId(entry), - }) - - const onContextMenu = (event: React.MouseEvent) => { - event.preventDefault() - contextMenu.show({ - event, - }) - } - - // close context menu on scroll - useEffect(() => { - const listener = () => contextMenu.hideAll() - const throttledListener = throttle(100, listener) - - window.addEventListener("scroll", throttledListener) - return () => window.removeEventListener("scroll", throttledListener) - }, [contextMenu]) - - return { onContextMenu } -}