feat: enable hover to read after hovering list for 1 second
This commit is contained in:
parent
035093e411
commit
56e3df3fe5
|
|
@ -2,8 +2,9 @@ import { Tabs, TabsList, TabsTrigger } from "@renderer/components/ui/tabs"
|
|||
import { cn } from "@renderer/lib/utils"
|
||||
import { useEntries } from "@renderer/queries/entries"
|
||||
import { useFeedStore } from "@renderer/store"
|
||||
import { useHover } from "@use-gesture/react"
|
||||
import { m } from "framer-motion"
|
||||
import { useState } from "react"
|
||||
import { useRef, useState } from "react"
|
||||
|
||||
import { ArticleItem } from "./article-item"
|
||||
import { EntryItemWrapper } from "./item-wrapper"
|
||||
|
|
@ -16,6 +17,7 @@ const gridMode = new Set([2, 3])
|
|||
|
||||
export function EntryColumn() {
|
||||
const [filterTab, setFilterTab] = useState("unread")
|
||||
const [focused, setFocused] = useState(false)
|
||||
|
||||
const activeList = useFeedStore((state) => state.activeList)
|
||||
const entries = useEntries({
|
||||
|
|
@ -25,6 +27,26 @@ export function EntryColumn() {
|
|||
...(filterTab === "unread" && { read: false }),
|
||||
})
|
||||
|
||||
const listRef = useRef<HTMLDivElement>(null)
|
||||
let focuseTimer: NodeJS.Timeout | null = null
|
||||
useHover(
|
||||
(state) => {
|
||||
if (state.active) {
|
||||
focuseTimer = setTimeout(() => {
|
||||
setFocused(true)
|
||||
}, 1000)
|
||||
} else {
|
||||
if (focuseTimer) {
|
||||
clearTimeout(focuseTimer)
|
||||
}
|
||||
setFocused(false)
|
||||
}
|
||||
},
|
||||
{
|
||||
target: listRef,
|
||||
},
|
||||
)
|
||||
|
||||
let Item
|
||||
switch (activeList?.view) {
|
||||
case 0: {
|
||||
|
|
@ -70,7 +92,7 @@ export function EntryColumn() {
|
|||
</TabsList>
|
||||
</Tabs>
|
||||
</div>
|
||||
<div>
|
||||
<div ref={listRef}>
|
||||
{entries.data?.pages?.map((page) => (
|
||||
<m.div
|
||||
key={`${activeList?.level}-${activeList?.id}`}
|
||||
|
|
@ -88,6 +110,7 @@ export function EntryColumn() {
|
|||
key={entry.entries.id}
|
||||
entry={entry}
|
||||
view={activeList?.view}
|
||||
hoverToRead={focused}
|
||||
>
|
||||
<Item entry={entry} />
|
||||
</EntryItemWrapper>
|
||||
|
|
|
|||
|
|
@ -7,16 +7,18 @@ import { apiFetch } from "@renderer/queries/api-fetch"
|
|||
import { feedActions, useFeedStore } from "@renderer/store"
|
||||
import { useMutation } from "@tanstack/react-query"
|
||||
import { useHover } from "@use-gesture/react"
|
||||
import { useRef } from "react"
|
||||
import { useEffect, useRef, useState } from "react"
|
||||
|
||||
export function EntryItemWrapper({
|
||||
entry,
|
||||
children,
|
||||
view,
|
||||
hoverToRead,
|
||||
}: {
|
||||
entry: EntriesResponse[number] | EntryResponse
|
||||
children: React.ReactNode
|
||||
view?: number
|
||||
hoverToRead: boolean
|
||||
}) {
|
||||
const { items } = useEntryActions({
|
||||
view,
|
||||
|
|
@ -46,16 +48,24 @@ export function EntryItemWrapper({
|
|||
})
|
||||
|
||||
const itemRef = useRef<HTMLDivElement>(null)
|
||||
const [hovered, setHovered] = useState(false)
|
||||
useHover(
|
||||
(state) => {
|
||||
if (state.active && !entry.read) {
|
||||
if (hoverToRead && state.active) {
|
||||
read.mutate()
|
||||
}
|
||||
setHovered(state.active)
|
||||
},
|
||||
{
|
||||
target: itemRef,
|
||||
enabled: !entry.read,
|
||||
},
|
||||
)
|
||||
useEffect(() => {
|
||||
if (hoverToRead && hovered) {
|
||||
read.mutate()
|
||||
}
|
||||
}, [hoverToRead, hovered, read])
|
||||
|
||||
if (!entry?.entries.url || view === undefined) return children
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue