diff --git a/src/components/Article/SearchAndSortBar.jsx b/src/components/Article/SearchAndSortBar.jsx index 5ce363696..2b26e4d91 100644 --- a/src/components/Article/SearchAndSortBar.jsx +++ b/src/components/Article/SearchAndSortBar.jsx @@ -23,7 +23,13 @@ import SidebarTrigger from "./SidebarTrigger.jsx" import CustomTooltip from "@/components/ui/CustomTooltip" import { polyglotState } from "@/hooks/useLanguage" import useScreenWidth from "@/hooks/useScreenWidth" -import { contentState, setFilterDate, setFilterString, setFilterType } from "@/store/contentState" +import { + contentState, + dynamicCountState, + setFilterDate, + setFilterString, + setFilterType, +} from "@/store/contentState" import { categoriesState, feedsState } from "@/store/dataState" import { settingsState, updateSettings } from "@/store/settingsState" import { getStartOfToday } from "@/utils/date" @@ -134,11 +140,12 @@ const ActiveButton = ({ active, icon, tooltip, onClick }) => ( ) const SearchAndSortBar = () => { - const { filterDate, filterString, infoFrom, isArticleListReady, total } = useStore(contentState) + const { filterDate, filterString, infoFrom, isArticleListReady } = useStore(contentState) const { orderDirection, showStatus } = useStore(settingsState) const { polyglot } = useStore(polyglotState) const feeds = useStore(feedsState) const categories = useStore(categoriesState) + const dynamicCount = useStore(dynamicCountState) const location = useLocation() const { id } = useParams() @@ -152,24 +159,24 @@ const SearchAndSortBar = () => { if (id) { if (infoFrom === "category") { const category = categories.find((c) => c.id === Number(id)) - return { title: category?.title, count: total } + return { title: category?.title, count: dynamicCount } } if (infoFrom === "feed") { const feed = feeds.find((f) => f.id === Number(id)) - return { title: feed?.title, count: total } + return { title: feed?.title, count: dynamicCount } } } const infoMap = { - all: { key: "sidebar.all", count: total }, - today: { key: "sidebar.today", count: total }, - starred: { key: "sidebar.starred", count: total }, - history: { key: "sidebar.history", count: total }, + all: { key: "sidebar.all", count: dynamicCount }, + today: { key: "sidebar.today", count: dynamicCount }, + starred: { key: "sidebar.starred", count: dynamicCount }, + history: { key: "sidebar.history", count: dynamicCount }, } const info = infoMap[infoFrom] || { key: "", count: 0 } return { title: info.key ? polyglot.t(info.key) : "", count: info.count } - }, [infoFrom, id, categories, feeds, total, polyglot]) + }, [infoFrom, id, categories, feeds, dynamicCount, polyglot]) const toggleOrderDirection = () => { const newOrderDirection = orderDirection === "desc" ? "asc" : "desc" diff --git a/src/components/Content/Content.jsx b/src/components/Content/Content.jsx index 581731b6e..739f61faf 100644 --- a/src/components/Content/Content.jsx +++ b/src/components/Content/Content.jsx @@ -21,7 +21,13 @@ import useEntryActions from "@/hooks/useEntryActions" import useKeyHandlers from "@/hooks/useKeyHandlers" import { polyglotState } from "@/hooks/useLanguage" import useScreenWidth from "@/hooks/useScreenWidth" -import { contentState, setActiveContent, setInfoFrom, setOffset } from "@/store/contentState" +import { + contentState, + setActiveContent, + setInfoFrom, + setInfoId, + setOffset, +} from "@/store/contentState" import { dataState } from "@/store/dataState" import { duplicateHotkeysState, hotkeysState } from "@/store/hotkeysState" import { settingsState } from "@/store/settingsState" @@ -168,6 +174,7 @@ const Content = ({ info, getEntries, markAllAsRead }) => { useEffect(() => { setInfoFrom(info.from) + setInfoId(info.id) if (activeContent) { setActiveContent(null) } diff --git a/src/components/Content/FooterPanel.jsx b/src/components/Content/FooterPanel.jsx index a1892fe9b..a7cd38a79 100644 --- a/src/components/Content/FooterPanel.jsx +++ b/src/components/Content/FooterPanel.jsx @@ -7,6 +7,7 @@ import { IconStarFill, } from "@arco-design/web-react/icon" import { useStore } from "@nanostores/react" +import { useEffect } from "react" import { getCounters } from "@/apis" import CustomTooltip from "@/components/ui/CustomTooltip" @@ -104,6 +105,12 @@ const FooterPanel = ({ info, refreshArticleList, markAllAsRead }) => { ) } + useEffect(() => { + if (info.from === "starred" && showStatus !== "unread") { + updateSettings({ showStatus: "all" }) + } + }, [info.from, showStatus]) + return (
{ setHistoryCount(response.total) break case "starred": - if (showStatus !== "unread") { + if (showStatus === "unread") { + setUnreadStarredCount(response.total) + } else { setStarredCount(response.total) } break diff --git a/src/store/contentState.js b/src/store/contentState.js index edd633636..5fbf0b623 100644 --- a/src/store/contentState.js +++ b/src/store/contentState.js @@ -1,6 +1,6 @@ import { computed, map } from "nanostores" -import { dataState, hiddenFeedIdsState } from "./dataState" +import { dataState, feedsState, hiddenFeedIdsState, unreadTotalState } from "./dataState" import { getSettings, settingsState } from "./settingsState" import removeDuplicateEntries from "@/utils/deduplicate" @@ -15,6 +15,7 @@ const defaultValue = { filterString: "", // 搜索文本 filterType: "title", // title | content | author infoFrom: getSettings("homePage"), // all | today | starred | history + infoId: null, // feed 或 category 的 id isArticleListReady: false, // 文章列表是否加载完成 isArticleLoading: false, // 文章是否正在加载 loadMoreVisible: false, // 加载更多元素可见性 @@ -46,6 +47,49 @@ export const filteredEntriesState = computed( }, ) +export const dynamicCountState = computed( + [contentState, dataState, unreadTotalState, settingsState, feedsState], + (content, data, unreadTotal, settings, feeds) => { + const { infoFrom, total } = content + const { showStatus } = settings + const { unreadStarredCount, unreadTodayCount, historyCount, starredCount, unreadInfo } = data + + if (infoFrom === "starred") { + return showStatus === "unread" ? unreadStarredCount : starredCount + } + + if (infoFrom === "history") { + return historyCount + } + + if (showStatus === "unread") { + switch (infoFrom) { + case "all": + return unreadTotal + case "today": + return unreadTodayCount + case "feed": { + const id = content.infoId + if (id) { + return unreadInfo[id] || 0 + } + return total + } + case "category": { + const id = content.infoId + if (id) { + const feedsInCategory = feeds.filter((feed) => feed.category.id === Number(id)) + return feedsInCategory.reduce((acc, feed) => acc + (unreadInfo[feed.id] || 0), 0) + } + return total + } + } + } + + return total + }, +) + export const activeEntryIndexState = computed( [contentState, filteredEntriesState], (content, filteredEntries) => { @@ -77,6 +121,7 @@ export const setFilterDate = createSetter(contentState, "filterDate") export const setFilterString = createSetter(contentState, "filterString") export const setFilterType = createSetter(contentState, "filterType") export const setInfoFrom = createSetter(contentState, "infoFrom") +export const setInfoId = createSetter(contentState, "infoId") export const setIsArticleListReady = createSetter(contentState, "isArticleListReady") export const setIsArticleLoading = createSetter(contentState, "isArticleLoading") export const setLoadMoreVisible = createSetter(contentState, "loadMoreVisible") diff --git a/src/store/dataState.js b/src/store/dataState.js index 57c5c4118..a36e514bd 100644 --- a/src/store/dataState.js +++ b/src/store/dataState.js @@ -7,6 +7,7 @@ import createSetter from "@/utils/nanostores" const defaultValue = { isAppDataReady: false, unreadInfo: {}, + unreadStarredCount: 0, unreadTodayCount: 0, starredCount: 0, historyCount: 0, @@ -101,6 +102,7 @@ export const setHistoryCount = createSetter(dataState, "historyCount") export const setIsAppDataReady = createSetter(dataState, "isAppDataReady") export const setStarredCount = createSetter(dataState, "starredCount") export const setUnreadInfo = createSetter(dataState, "unreadInfo") +export const setUnreadStarredCount = createSetter(dataState, "unreadStarredCount") export const setUnreadTodayCount = createSetter(dataState, "unreadTodayCount") export const setVersion = createSetter(dataState, "version") export const resetData = () => dataState.set(defaultValue)