From 6b8572c37aa287aa544e6ddb2847693ba597b0be Mon Sep 17 00:00:00 2001
From: Stephen Zhou <38493346+hyoban@users.noreply.github.com>
Date: Mon, 11 Nov 2024 11:40:59 +0800
Subject: [PATCH] fix: allow selecting when meta key is pressed
---
.../renderer/src/modules/feed-column/list.tsx | 19 +++++-------
packages/hooks/src/index.ts | 1 +
packages/hooks/src/useKeyPressing.ts | 29 +++++++++++++++++++
3 files changed, 38 insertions(+), 11 deletions(-)
create mode 100644 packages/hooks/src/useKeyPressing.ts
diff --git a/apps/renderer/src/modules/feed-column/list.tsx b/apps/renderer/src/modules/feed-column/list.tsx
index eeb7f87231..98ffb87130 100644
--- a/apps/renderer/src/modules/feed-column/list.tsx
+++ b/apps/renderer/src/modules/feed-column/list.tsx
@@ -2,6 +2,7 @@ import { useDraggable } from "@dnd-kit/core"
import { ScrollArea } from "@follow/components/ui/scroll-area/index.js"
import type { FeedViewType } from "@follow/constants"
import { views } from "@follow/constants"
+import { useKeyPressing } from "@follow/hooks"
import { stopPropagation } from "@follow/utils/dom"
import { cn } from "@follow/utils/utils"
import * as HoverCard from "@radix-ui/react-hover-card"
@@ -190,6 +191,8 @@ function FeedListImpl({ className, view }: { className?: string; view: number })
const shouldFreeUpSpace = useShouldFreeUpSpace()
+ const isMetaKeyPressed = useKeyPressing("Meta")
+
return (
@@ -198,24 +201,18 @@ function FeedListImpl({ className, view }: { className?: string; view: number })
ref={selectoRef}
rootContainer={document.body}
dragContainer={"#feeds-area"}
- dragCondition={() => selectedFeedIds.length === 0}
+ dragCondition={() => selectedFeedIds.length === 0 || isMetaKeyPressed}
selectableTargets={["[data-feed-id]"]}
continueSelect
hitRate={10}
onSelect={(e) => {
const allChanged = [...e.added, ...e.removed]
+ .map((el) => el.dataset.feedId)
+ .filter((id) => id !== undefined)
setSelectedFeedIds((prev) => {
- const added = allChanged
- .map((el) => el.dataset.feedId)
- .filter((id) => id !== undefined)
- .filter((id) => !prev.includes(id))
- const removed = new Set(
- allChanged
- .map((el) => el.dataset.feedId)
- .filter((id) => id !== undefined)
- .filter((id) => prev.includes(id)),
- )
+ const added = allChanged.filter((id) => !prev.includes(id))
+ const removed = new Set(allChanged.filter((id) => prev.includes(id)))
return [...prev.filter((id) => !removed.has(id)), ...added]
})
}}
diff --git a/packages/hooks/src/index.ts b/packages/hooks/src/index.ts
index cc321c9baf..5579cf1d98 100644
--- a/packages/hooks/src/index.ts
+++ b/packages/hooks/src/index.ts
@@ -5,6 +5,7 @@ export * from "./useDark"
export * from "./useInputComposition"
export * from "./useInterval"
export * from "./useIsOnline"
+export * from "./useKeyPressing"
export * from "./useMeasure"
export * from "./useOnce"
export * from "./usePageVisibility"
diff --git a/packages/hooks/src/useKeyPressing.ts b/packages/hooks/src/useKeyPressing.ts
new file mode 100644
index 0000000000..04fc8a0581
--- /dev/null
+++ b/packages/hooks/src/useKeyPressing.ts
@@ -0,0 +1,29 @@
+import { useEffect, useMemo, useState } from "react"
+
+export function useKeyPressing(key: string) {
+ const [keysPressed, setKeysPressed] = useState(() => new Set())
+
+ useEffect(() => {
+ const handleKeyDown = (event: KeyboardEvent) => {
+ setKeysPressed((prev) => new Set(prev).add(event.key))
+ }
+
+ const handleKeyUp = (event: KeyboardEvent) => {
+ setKeysPressed((prev) => {
+ const newSet = new Set(prev)
+ newSet.delete(event.key)
+ return newSet
+ })
+ }
+
+ window.addEventListener("keydown", handleKeyDown)
+ window.addEventListener("keyup", handleKeyUp)
+
+ return () => {
+ window.removeEventListener("keydown", handleKeyDown)
+ window.removeEventListener("keyup", handleKeyUp)
+ }
+ }, [])
+
+ return useMemo(() => keysPressed.has(key), [keysPressed, key])
+}