Skip to content

Commit 471367e

Browse files
committed
feat(content): add dynamic count state and optimize article filtering
1 parent 2fac528 commit 471367e

File tree

6 files changed

+83
-12
lines changed

6 files changed

+83
-12
lines changed

src/components/Article/SearchAndSortBar.jsx

+16-9
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,13 @@ import SidebarTrigger from "./SidebarTrigger.jsx"
2323
import CustomTooltip from "@/components/ui/CustomTooltip"
2424
import { polyglotState } from "@/hooks/useLanguage"
2525
import useScreenWidth from "@/hooks/useScreenWidth"
26-
import { contentState, setFilterDate, setFilterString, setFilterType } from "@/store/contentState"
26+
import {
27+
contentState,
28+
dynamicCountState,
29+
setFilterDate,
30+
setFilterString,
31+
setFilterType,
32+
} from "@/store/contentState"
2733
import { categoriesState, feedsState } from "@/store/dataState"
2834
import { settingsState, updateSettings } from "@/store/settingsState"
2935
import { getStartOfToday } from "@/utils/date"
@@ -134,11 +140,12 @@ const ActiveButton = ({ active, icon, tooltip, onClick }) => (
134140
)
135141

136142
const SearchAndSortBar = () => {
137-
const { filterDate, filterString, infoFrom, isArticleListReady, total } = useStore(contentState)
143+
const { filterDate, filterString, infoFrom, isArticleListReady } = useStore(contentState)
138144
const { orderDirection, showStatus } = useStore(settingsState)
139145
const { polyglot } = useStore(polyglotState)
140146
const feeds = useStore(feedsState)
141147
const categories = useStore(categoriesState)
148+
const dynamicCount = useStore(dynamicCountState)
142149

143150
const location = useLocation()
144151
const { id } = useParams()
@@ -152,24 +159,24 @@ const SearchAndSortBar = () => {
152159
if (id) {
153160
if (infoFrom === "category") {
154161
const category = categories.find((c) => c.id === Number(id))
155-
return { title: category?.title, count: total }
162+
return { title: category?.title, count: dynamicCount }
156163
}
157164
if (infoFrom === "feed") {
158165
const feed = feeds.find((f) => f.id === Number(id))
159-
return { title: feed?.title, count: total }
166+
return { title: feed?.title, count: dynamicCount }
160167
}
161168
}
162169

163170
const infoMap = {
164-
all: { key: "sidebar.all", count: total },
165-
today: { key: "sidebar.today", count: total },
166-
starred: { key: "sidebar.starred", count: total },
167-
history: { key: "sidebar.history", count: total },
171+
all: { key: "sidebar.all", count: dynamicCount },
172+
today: { key: "sidebar.today", count: dynamicCount },
173+
starred: { key: "sidebar.starred", count: dynamicCount },
174+
history: { key: "sidebar.history", count: dynamicCount },
168175
}
169176

170177
const info = infoMap[infoFrom] || { key: "", count: 0 }
171178
return { title: info.key ? polyglot.t(info.key) : "", count: info.count }
172-
}, [infoFrom, id, categories, feeds, total, polyglot])
179+
}, [infoFrom, id, categories, feeds, dynamicCount, polyglot])
173180

174181
const toggleOrderDirection = () => {
175182
const newOrderDirection = orderDirection === "desc" ? "asc" : "desc"

src/components/Content/Content.jsx

+8-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,13 @@ import useEntryActions from "@/hooks/useEntryActions"
2121
import useKeyHandlers from "@/hooks/useKeyHandlers"
2222
import { polyglotState } from "@/hooks/useLanguage"
2323
import useScreenWidth from "@/hooks/useScreenWidth"
24-
import { contentState, setActiveContent, setInfoFrom, setOffset } from "@/store/contentState"
24+
import {
25+
contentState,
26+
setActiveContent,
27+
setInfoFrom,
28+
setInfoId,
29+
setOffset,
30+
} from "@/store/contentState"
2531
import { dataState } from "@/store/dataState"
2632
import { duplicateHotkeysState, hotkeysState } from "@/store/hotkeysState"
2733
import { settingsState } from "@/store/settingsState"
@@ -168,6 +174,7 @@ const Content = ({ info, getEntries, markAllAsRead }) => {
168174

169175
useEffect(() => {
170176
setInfoFrom(info.from)
177+
setInfoId(info.id)
171178
if (activeContent) {
172179
setActiveContent(null)
173180
}

src/components/Content/FooterPanel.jsx

+7
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
IconStarFill,
88
} from "@arco-design/web-react/icon"
99
import { useStore } from "@nanostores/react"
10+
import { useEffect } from "react"
1011

1112
import { getCounters } from "@/apis"
1213
import CustomTooltip from "@/components/ui/CustomTooltip"
@@ -104,6 +105,12 @@ const FooterPanel = ({ info, refreshArticleList, markAllAsRead }) => {
104105
)
105106
}
106107

108+
useEffect(() => {
109+
if (info.from === "starred" && showStatus !== "unread") {
110+
updateSettings({ showStatus: "all" })
111+
}
112+
}, [info.from, showStatus])
113+
107114
return (
108115
<div className="entry-panel">
109116
<Popconfirm

src/hooks/useArticleList.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
setHistoryCount,
1414
setStarredCount,
1515
setUnreadInfo,
16+
setUnreadStarredCount,
1617
setUnreadTodayCount,
1718
} from "@/store/dataState"
1819
import { settingsState } from "@/store/settingsState"
@@ -71,7 +72,9 @@ const useArticleList = (info, getEntries) => {
7172
setHistoryCount(response.total)
7273
break
7374
case "starred":
74-
if (showStatus !== "unread") {
75+
if (showStatus === "unread") {
76+
setUnreadStarredCount(response.total)
77+
} else {
7578
setStarredCount(response.total)
7679
}
7780
break

src/store/contentState.js

+46-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { computed, map } from "nanostores"
22

3-
import { dataState, hiddenFeedIdsState } from "./dataState"
3+
import { dataState, feedsState, hiddenFeedIdsState, unreadTotalState } from "./dataState"
44
import { getSettings, settingsState } from "./settingsState"
55

66
import removeDuplicateEntries from "@/utils/deduplicate"
@@ -15,6 +15,7 @@ const defaultValue = {
1515
filterString: "", // 搜索文本
1616
filterType: "title", // title | content | author
1717
infoFrom: getSettings("homePage"), // all | today | starred | history
18+
infoId: null, // feed 或 category 的 id
1819
isArticleListReady: false, // 文章列表是否加载完成
1920
isArticleLoading: false, // 文章是否正在加载
2021
loadMoreVisible: false, // 加载更多元素可见性
@@ -46,6 +47,49 @@ export const filteredEntriesState = computed(
4647
},
4748
)
4849

50+
export const dynamicCountState = computed(
51+
[contentState, dataState, unreadTotalState, settingsState, feedsState],
52+
(content, data, unreadTotal, settings, feeds) => {
53+
const { infoFrom, total } = content
54+
const { showStatus } = settings
55+
const { unreadStarredCount, unreadTodayCount, historyCount, starredCount, unreadInfo } = data
56+
57+
if (infoFrom === "starred") {
58+
return showStatus === "unread" ? unreadStarredCount : starredCount
59+
}
60+
61+
if (infoFrom === "history") {
62+
return historyCount
63+
}
64+
65+
if (showStatus === "unread") {
66+
switch (infoFrom) {
67+
case "all":
68+
return unreadTotal
69+
case "today":
70+
return unreadTodayCount
71+
case "feed": {
72+
const id = content.infoId
73+
if (id) {
74+
return unreadInfo[id] || 0
75+
}
76+
return total
77+
}
78+
case "category": {
79+
const id = content.infoId
80+
if (id) {
81+
const feedsInCategory = feeds.filter((feed) => feed.category.id === Number(id))
82+
return feedsInCategory.reduce((acc, feed) => acc + (unreadInfo[feed.id] || 0), 0)
83+
}
84+
return total
85+
}
86+
}
87+
}
88+
89+
return total
90+
},
91+
)
92+
4993
export const activeEntryIndexState = computed(
5094
[contentState, filteredEntriesState],
5195
(content, filteredEntries) => {
@@ -77,6 +121,7 @@ export const setFilterDate = createSetter(contentState, "filterDate")
77121
export const setFilterString = createSetter(contentState, "filterString")
78122
export const setFilterType = createSetter(contentState, "filterType")
79123
export const setInfoFrom = createSetter(contentState, "infoFrom")
124+
export const setInfoId = createSetter(contentState, "infoId")
80125
export const setIsArticleListReady = createSetter(contentState, "isArticleListReady")
81126
export const setIsArticleLoading = createSetter(contentState, "isArticleLoading")
82127
export const setLoadMoreVisible = createSetter(contentState, "loadMoreVisible")

src/store/dataState.js

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import createSetter from "@/utils/nanostores"
77
const defaultValue = {
88
isAppDataReady: false,
99
unreadInfo: {},
10+
unreadStarredCount: 0,
1011
unreadTodayCount: 0,
1112
starredCount: 0,
1213
historyCount: 0,
@@ -101,6 +102,7 @@ export const setHistoryCount = createSetter(dataState, "historyCount")
101102
export const setIsAppDataReady = createSetter(dataState, "isAppDataReady")
102103
export const setStarredCount = createSetter(dataState, "starredCount")
103104
export const setUnreadInfo = createSetter(dataState, "unreadInfo")
105+
export const setUnreadStarredCount = createSetter(dataState, "unreadStarredCount")
104106
export const setUnreadTodayCount = createSetter(dataState, "unreadTodayCount")
105107
export const setVersion = createSetter(dataState, "version")
106108
export const resetData = () => dataState.set(defaultValue)

0 commit comments

Comments
 (0)