diff --git a/commafeed-client/src/app/store.ts b/commafeed-client/src/app/store.ts index 6aa22e59..7dac25d9 100644 --- a/commafeed-client/src/app/store.ts +++ b/commafeed-client/src/app/store.ts @@ -1,5 +1,5 @@ import { configureStore } from "@reduxjs/toolkit" -import { type TypedUseSelectorHook, useDispatch, useSelector } from "react-redux" +import { shallowEqual, type TypedUseSelectorHook, useDispatch, useSelector } from "react-redux" import { entriesSlice } from "@/app/entries/slice" import { redirectSlice } from "@/app/redirect/slice" import { serverSlice } from "@/app/server/slice" @@ -41,3 +41,4 @@ export type AppDispatch = typeof store.dispatch export const useAppDispatch: () => AppDispatch = useDispatch export const useAppSelector: TypedUseSelectorHook = useSelector +export const useShallowEqualAppSelector: TypedUseSelectorHook = selector => useSelector(selector, shallowEqual) diff --git a/commafeed-client/src/pages/app/FeedEntriesPage.tsx b/commafeed-client/src/pages/app/FeedEntriesPage.tsx index 2e60841f..9a2f0611 100644 --- a/commafeed-client/src/pages/app/FeedEntriesPage.tsx +++ b/commafeed-client/src/pages/app/FeedEntriesPage.tsx @@ -8,7 +8,7 @@ import { Constants } from "@/app/constants" import type { EntrySourceType } from "@/app/entries/slice" import { loadEntries } from "@/app/entries/thunks" import { redirectToCategoryDetails, redirectToFeedDetails, redirectToTagDetails } from "@/app/redirect/thunks" -import { useAppDispatch, useAppSelector } from "@/app/store" +import { useAppDispatch, useAppSelector, useShallowEqualAppSelector } from "@/app/store" import { categoryHasNewEntries, categoryUnreadCount, flattenCategoryTree } from "@/app/utils" import { FeedEntries } from "@/components/content/FeedEntries" import { UnreadCount } from "@/components/sidebar/UnreadCount" @@ -52,39 +52,29 @@ export function FeedEntriesPage(props: Readonly) { const hasMore = useAppSelector(state => state.entries.hasMore) const mobile = useMobile() const sidebarVisible = useAppSelector(state => state.tree.sidebarVisible) - const unreadCount = useAppSelector(state => { + const { unreadCount, hasNewEntries } = useShallowEqualAppSelector(state => { const root = state.tree.rootCategory - if (!root) return 0 + if (!root) return { unreadCount: 0, hasNewEntries: false } + if (props.sourceType === "category") { - if (id === Constants.categories.starred.id) return 0 - if (id === Constants.categories.all.id) return categoryUnreadCount(root) - const category = flattenCategoryTree(root).find(c => c.id === id) - return categoryUnreadCount(category) + const category = id === Constants.categories.all.id ? root : flattenCategoryTree(root).find(c => c.id === id) + return { + unreadCount: categoryUnreadCount(category), + hasNewEntries: categoryHasNewEntries(category), + } } + if (props.sourceType === "feed") { - return ( - flattenCategoryTree(root) - .flatMap(c => c.feeds) - .find(f => String(f.id) === id)?.unread ?? 0 - ) - } - return 0 - }) - const hasNewEntries = useAppSelector(state => { - const root = state.tree.rootCategory - if (!root) return false - if (props.sourceType === "category") { - if (id === Constants.categories.starred.id) return false - if (id === Constants.categories.all.id) return categoryHasNewEntries(root) - const category = flattenCategoryTree(root).find(c => c.id === id) - return categoryHasNewEntries(category) - } - if (props.sourceType === "feed") { - return !!flattenCategoryTree(root) + const feed = flattenCategoryTree(root) .flatMap(c => c.feeds) - .find(f => String(f.id) === id)?.hasNewEntries + .find(f => f.id === +id) + return { + unreadCount: feed?.unread ?? 0, + hasNewEntries: !!feed?.hasNewEntries, + } } - return false + + return { unreadCount: 0, hasNewEntries: false } }) const showUnreadCount = mobile || !sidebarVisible const dispatch = useAppDispatch()