Skip to content

Commit 1f349ed

Browse files
authored
fix: improve perform for feed column (#1708)
1 parent 0f32364 commit 1f349ed

File tree

11 files changed

+175
-158
lines changed

11 files changed

+175
-158
lines changed
Lines changed: 115 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { FeedViewType } from "@follow/constants"
2-
import { useCallback } from "react"
2+
import { useCallback, useMemo } from "react"
33

44
import {
55
getReadabilityStatus,
@@ -72,107 +72,120 @@ export const useEntryActions = ({ entryId, view }: { entryId: string; view?: Fee
7272
const isShowSourceContent = useShowSourceContent()
7373
const getCmd = useGetCommand()
7474
const runCmdFn = useRunCommandFn()
75-
if (!entryId) return []
76-
const actionConfigs = [
77-
{
78-
id: COMMAND_ID.integration.saveToEagle,
79-
onClick: runCmdFn(COMMAND_ID.integration.saveToEagle, [{ entryId }]),
80-
},
81-
{
82-
id: COMMAND_ID.integration.saveToReadwise,
83-
onClick: runCmdFn(COMMAND_ID.integration.saveToReadwise, [{ entryId }]),
84-
},
85-
{
86-
id: COMMAND_ID.integration.saveToInstapaper,
87-
onClick: runCmdFn(COMMAND_ID.integration.saveToInstapaper, [{ entryId }]),
88-
},
89-
{
90-
id: COMMAND_ID.integration.saveToOmnivore,
91-
onClick: runCmdFn(COMMAND_ID.integration.saveToOmnivore, [{ entryId }]),
92-
},
93-
{
94-
id: COMMAND_ID.integration.saveToObsidian,
95-
onClick: runCmdFn(COMMAND_ID.integration.saveToObsidian, [{ entryId }]),
96-
},
97-
{
98-
id: COMMAND_ID.integration.saveToOutline,
99-
onClick: runCmdFn(COMMAND_ID.integration.saveToOutline, [{ entryId }]),
100-
},
101-
{
102-
id: COMMAND_ID.entry.tip,
103-
onClick: runCmdFn(COMMAND_ID.entry.tip, [{ entryId, feedId: feed?.id }]),
104-
hide: isInbox || feed?.ownerUserId === whoami()?.id,
105-
shortcut: shortcuts.entry.tip.key,
106-
},
107-
{
108-
id: COMMAND_ID.entry.unstar,
109-
onClick: runCmdFn(COMMAND_ID.entry.unstar, [{ entryId }]),
110-
hide: !entry?.collections,
111-
shortcut: shortcuts.entry.toggleStarred.key,
112-
},
113-
{
114-
id: COMMAND_ID.entry.star,
115-
onClick: runCmdFn(COMMAND_ID.entry.star, [{ entryId, view }]),
116-
hide: !!entry?.collections,
117-
shortcut: shortcuts.entry.toggleStarred.key,
118-
},
119-
{
120-
id: COMMAND_ID.entry.delete,
121-
onClick: runCmdFn(COMMAND_ID.entry.delete, [{ entryId }]),
122-
hide: !isInbox,
123-
shortcut: shortcuts.entry.copyLink.key,
124-
},
125-
{
126-
id: COMMAND_ID.entry.copyLink,
127-
onClick: runCmdFn(COMMAND_ID.entry.copyLink, [{ entryId }]),
128-
hide: !entry?.entries.url,
129-
shortcut: shortcuts.entry.copyTitle.key,
130-
},
131-
{
132-
id: COMMAND_ID.entry.openInBrowser,
133-
onClick: runCmdFn(COMMAND_ID.entry.openInBrowser, [{ entryId }]),
134-
},
135-
{
136-
id: COMMAND_ID.entry.viewSourceContent,
137-
onClick: runCmdFn(COMMAND_ID.entry.viewSourceContent, [{ entryId }]),
138-
hide: isShowSourceContent || !entry?.entries.url,
139-
},
140-
{
141-
id: COMMAND_ID.entry.viewEntryContent,
142-
onClick: runCmdFn(COMMAND_ID.entry.viewEntryContent, []),
143-
hide: !isShowSourceContent,
144-
active: true,
145-
},
146-
{
147-
id: COMMAND_ID.entry.share,
148-
onClick: runCmdFn(COMMAND_ID.entry.share, [{ entryId }]),
149-
hide: !entry?.entries.url || !("share" in navigator),
150-
shortcut: shortcuts.entry.share.key,
151-
},
152-
{
153-
id: COMMAND_ID.entry.read,
154-
onClick: runCmdFn(COMMAND_ID.entry.read, [{ entryId }]),
155-
hide: !entry || !!entry.read || !!entry.collections || !!inList,
156-
shortcut: shortcuts.entry.toggleRead.key,
157-
},
158-
{
159-
id: COMMAND_ID.entry.unread,
160-
onClick: runCmdFn(COMMAND_ID.entry.unread, [{ entryId }]),
161-
hide: !entry || !entry.read || !!entry.collections || !!inList,
162-
shortcut: shortcuts.entry.toggleRead.key,
163-
},
164-
]
165-
.filter((config) => !config.hide)
166-
.map((config) => {
167-
const cmd = getCmd(config.id)
168-
if (!cmd) return null
169-
return {
170-
...config,
171-
name: cmd.label.title,
172-
icon: cmd.icon,
173-
}
174-
})
175-
.filter((i) => i !== null)
75+
const actionConfigs = useMemo(() => {
76+
if (!entryId) return []
77+
return [
78+
{
79+
id: COMMAND_ID.integration.saveToEagle,
80+
onClick: runCmdFn(COMMAND_ID.integration.saveToEagle, [{ entryId }]),
81+
},
82+
{
83+
id: COMMAND_ID.integration.saveToReadwise,
84+
onClick: runCmdFn(COMMAND_ID.integration.saveToReadwise, [{ entryId }]),
85+
},
86+
{
87+
id: COMMAND_ID.integration.saveToInstapaper,
88+
onClick: runCmdFn(COMMAND_ID.integration.saveToInstapaper, [{ entryId }]),
89+
},
90+
{
91+
id: COMMAND_ID.integration.saveToOmnivore,
92+
onClick: runCmdFn(COMMAND_ID.integration.saveToOmnivore, [{ entryId }]),
93+
},
94+
{
95+
id: COMMAND_ID.integration.saveToObsidian,
96+
onClick: runCmdFn(COMMAND_ID.integration.saveToObsidian, [{ entryId }]),
97+
},
98+
{
99+
id: COMMAND_ID.integration.saveToOutline,
100+
onClick: runCmdFn(COMMAND_ID.integration.saveToOutline, [{ entryId }]),
101+
},
102+
{
103+
id: COMMAND_ID.entry.tip,
104+
onClick: runCmdFn(COMMAND_ID.entry.tip, [{ entryId, feedId: feed?.id }]),
105+
hide: isInbox || feed?.ownerUserId === whoami()?.id,
106+
shortcut: shortcuts.entry.tip.key,
107+
},
108+
{
109+
id: COMMAND_ID.entry.unstar,
110+
onClick: runCmdFn(COMMAND_ID.entry.unstar, [{ entryId }]),
111+
hide: !entry?.collections,
112+
shortcut: shortcuts.entry.toggleStarred.key,
113+
},
114+
{
115+
id: COMMAND_ID.entry.star,
116+
onClick: runCmdFn(COMMAND_ID.entry.star, [{ entryId, view }]),
117+
hide: !!entry?.collections,
118+
shortcut: shortcuts.entry.toggleStarred.key,
119+
},
120+
{
121+
id: COMMAND_ID.entry.delete,
122+
onClick: runCmdFn(COMMAND_ID.entry.delete, [{ entryId }]),
123+
hide: !isInbox,
124+
shortcut: shortcuts.entry.copyLink.key,
125+
},
126+
{
127+
id: COMMAND_ID.entry.copyLink,
128+
onClick: runCmdFn(COMMAND_ID.entry.copyLink, [{ entryId }]),
129+
hide: !entry?.entries.url,
130+
shortcut: shortcuts.entry.copyTitle.key,
131+
},
132+
{
133+
id: COMMAND_ID.entry.openInBrowser,
134+
onClick: runCmdFn(COMMAND_ID.entry.openInBrowser, [{ entryId }]),
135+
},
136+
{
137+
id: COMMAND_ID.entry.viewSourceContent,
138+
onClick: runCmdFn(COMMAND_ID.entry.viewSourceContent, [{ entryId }]),
139+
hide: isShowSourceContent || !entry?.entries.url,
140+
},
141+
{
142+
id: COMMAND_ID.entry.viewEntryContent,
143+
onClick: runCmdFn(COMMAND_ID.entry.viewEntryContent, []),
144+
hide: !isShowSourceContent,
145+
active: true,
146+
},
147+
{
148+
id: COMMAND_ID.entry.share,
149+
onClick: runCmdFn(COMMAND_ID.entry.share, [{ entryId }]),
150+
hide: !entry?.entries.url || !("share" in navigator),
151+
shortcut: shortcuts.entry.share.key,
152+
},
153+
{
154+
id: COMMAND_ID.entry.read,
155+
onClick: runCmdFn(COMMAND_ID.entry.read, [{ entryId }]),
156+
hide: !entry || !!entry.read || !!entry.collections || !!inList,
157+
shortcut: shortcuts.entry.toggleRead.key,
158+
},
159+
{
160+
id: COMMAND_ID.entry.unread,
161+
onClick: runCmdFn(COMMAND_ID.entry.unread, [{ entryId }]),
162+
hide: !entry || !entry.read || !!entry.collections || !!inList,
163+
shortcut: shortcuts.entry.toggleRead.key,
164+
},
165+
]
166+
.filter((config) => !config.hide)
167+
.map((config) => {
168+
const cmd = getCmd(config.id)
169+
if (!cmd) return null
170+
return {
171+
...config,
172+
name: cmd.label.title,
173+
icon: cmd.icon,
174+
}
175+
})
176+
.filter((i) => i !== null)
177+
}, [
178+
entry,
179+
entryId,
180+
feed?.id,
181+
feed?.ownerUserId,
182+
getCmd,
183+
inList,
184+
isInbox,
185+
isShowSourceContent,
186+
runCmdFn,
187+
view,
188+
])
176189

177190
return actionConfigs
178191
}

apps/renderer/src/hooks/biz/useFeedActions.tsx

Lines changed: 6 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { env } from "@follow/shared/env"
55
import { UrlBuilder } from "@follow/utils/url-builder"
66
import { isBizId } from "@follow/utils/utils"
77
import { useMutation } from "@tanstack/react-query"
8-
import { useMemo, useRef } from "react"
8+
import { useMemo } from "react"
99
import { useTranslation } from "react-i18next"
1010
import { toast } from "sonner"
1111

@@ -19,7 +19,7 @@ import { FeedForm } from "~/modules/discover/feed-form"
1919
import { InboxForm } from "~/modules/discover/inbox-form"
2020
import { ListForm } from "~/modules/discover/list-form"
2121
import { ListCreationModalContent } from "~/modules/settings/tabs/lists/modals"
22-
import { entries } from "~/queries/entries"
22+
import { useResetFeed } from "~/queries/feed"
2323
import { getFeedById, useFeedById } from "~/store/feed"
2424
import { useInboxById } from "~/store/inbox"
2525
import { listActions, useListById, useOwnedListByView } from "~/store/list"
@@ -73,9 +73,7 @@ export const useFeedActions = ({
7373
const subscription = useSubscriptionByFeedId(feedId)
7474
const { present } = useModalStack()
7575
const deleteSubscription = useDeleteSubscription({})
76-
const claimFeed = useFeedClaimModal({
77-
feedId,
78-
})
76+
const claimFeed = useFeedClaimModal()
7977

8078
const navigateEntry = useNavigateEntry()
8179
const isEntryList = type === "entryList"
@@ -116,7 +114,7 @@ export const useFeedActions = ({
116114
: t("sidebar.feed_actions.claim"),
117115
shortcut: "C",
118116
click: () => {
119-
claimFeed()
117+
claimFeed({ feedId })
120118
},
121119
},
122120
...(isFeedOwner
@@ -331,7 +329,7 @@ export const useFeedActions = ({
331329
view,
332330
])
333331

334-
return { items }
332+
return items
335333
}
336334

337335
export const useListActions = ({ listId, view }: { listId: string; view: FeedViewType }) => {
@@ -424,7 +422,7 @@ export const useListActions = ({ listId, view }: { listId: string; view: FeedVie
424422
return items
425423
}, [list, t, present, deleteSubscription, subscription, navigateEntry, listId, view])
426424

427-
return { items }
425+
return items
428426
}
429427

430428
export const useInboxActions = ({ inboxId }: { inboxId: string }) => {
@@ -520,28 +518,3 @@ export const useRemoveFeedFromFeedList = (options?: {
520518
},
521519
})
522520
}
523-
524-
export const useResetFeed = () => {
525-
const { t } = useTranslation()
526-
const toastIDRef = useRef<string | number | null>(null)
527-
528-
return useMutation({
529-
mutationFn: async (feedId: string) => {
530-
toastIDRef.current = toast.loading(t("sidebar.feed_actions.resetting_feed"))
531-
await apiClient.feeds.reset.$get({ query: { id: feedId } })
532-
},
533-
onSuccess: (_, feedId) => {
534-
entries.entries({ feedId }).invalidateRoot()
535-
toast.success(
536-
t("sidebar.feed_actions.reset_feed_success"),
537-
toastIDRef.current ? { id: toastIDRef.current } : undefined,
538-
)
539-
},
540-
onError: () => {
541-
toast.error(
542-
t("sidebar.feed_actions.reset_feed_error"),
543-
toastIDRef.current ? { id: toastIDRef.current } : undefined,
544-
)
545-
},
546-
})
547-
}

apps/renderer/src/modules/claim/hooks.ts

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,23 @@ import { getFeedById } from "~/store/feed"
66

77
import { FeedClaimModalContent } from "./feed-claim-modal"
88

9-
export const useFeedClaimModal = ({ feedId }: { feedId?: string }) => {
9+
export const useFeedClaimModal = () => {
1010
const { present } = useModalStack()
1111
const { t } = useTranslation()
1212

13-
return useCallback(() => {
14-
if (!feedId) return
13+
return useCallback(
14+
({ feedId }: { feedId?: string }) => {
15+
if (!feedId) return
1516

16-
const feed = getFeedById(feedId)
17+
const feed = getFeedById(feedId)
1718

18-
if (!feed) return
19+
if (!feed) return
1920

20-
present({
21-
title: t("feed_claim_modal.title"),
22-
content: () => createElement(FeedClaimModalContent, { feedId }),
23-
})
24-
}, [feedId, present])
21+
present({
22+
title: t("feed_claim_modal.title"),
23+
content: () => createElement(FeedClaimModalContent, { feedId }),
24+
})
25+
},
26+
[present, t],
27+
)
2528
}

apps/renderer/src/modules/entry-column/layouts/EntryItemWrapper.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export const EntryItemWrapper: FC<
2525
} & PropsWithChildren
2626
> = ({ entry, view, children, itemClassName, style }) => {
2727
const actionConfigs = useEntryActions({ entryId: entry.entries.id })
28-
const { items: feedItems } = useFeedActions({
28+
const feedItems = useFeedActions({
2929
feedId: entry.feedId || entry.inboxId,
3030
view,
3131
type: "entryList",

apps/renderer/src/modules/feed-column/atom.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export const setFeedListSortOrder = (order: FeedListSortOrder) => {
3535
})
3636
}
3737

38+
export const SELECT_NOTHING = []
3839
export const [
3940
,
4041
useSelectedFeedIds,
@@ -43,7 +44,7 @@ export const [
4344
getSelectedFeedIds,
4445
setSelectedFeedIds,
4546
useSelectedFeedIdsSelector,
46-
] = createAtomHooks(atom<string[]>([]))
47+
] = createAtomHooks(atom<string[]>(SELECT_NOTHING))
4748

4849
export const [, , useFeedAreaScrollProgressValue, , , setFeedAreaScrollProgressValue] =
4950
createAtomHooks(atom(0))

apps/renderer/src/modules/feed-column/category.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ function FeedCategoryImpl({ data: ids, view, categoryOpenStateData }: FeedCatego
328328
</div>
329329
</div>
330330
)}
331-
<AnimatePresence>
331+
<AnimatePresence initial={false}>
332332
{open && (
333333
<m.div
334334
ref={itemsRef}

0 commit comments

Comments
 (0)