From 29176e8695c9944441e08e02bf46a9000bb283d3 Mon Sep 17 00:00:00 2001 From: Innei Date: Tue, 4 Jun 2024 19:41:07 +0800 Subject: [PATCH] fix: read all (#37) Signed-off-by: Innei --- .../src/components/entry-column/index.tsx | 15 ++++++- src/renderer/src/store/entry.ts | 43 ++++++++++++++++--- src/renderer/src/store/subscription.ts | 20 ++++++++- 3 files changed, 69 insertions(+), 9 deletions(-) diff --git a/src/renderer/src/components/entry-column/index.tsx b/src/renderer/src/components/entry-column/index.tsx index 6c3e8c979..8eae8516d 100644 --- a/src/renderer/src/components/entry-column/index.tsx +++ b/src/renderer/src/components/entry-column/index.tsx @@ -12,7 +12,11 @@ import { getEntriesParams } from "@renderer/lib/utils" import type { EntryModel } from "@renderer/models" import { apiClient } from "@renderer/queries/api-fetch" import { useEntries } from "@renderer/queries/entries" -import { feedActions, useFeedStore } from "@renderer/store" +import { + feedActions, + subscriptionActions, + useFeedStore, +} from "@renderer/store" import { entryActions } from "@renderer/store/entry" import { m } from "framer-motion" import { useAtom, useAtomValue } from "jotai" @@ -189,7 +193,14 @@ const ListHeader: FC = () => { }), }, }) - entryActions.optimisticUpdateAll({ read: true }) + + if (typeof activeList.id === "number") { + subscriptionActions.markReadByView(activeList.view) + } else { + activeList.id.split(",").forEach((feedId) => { + entryActions.markReadByFeedId(feedId) + }) + } setMarkPopoverOpen(false) }, [activeList]) diff --git a/src/renderer/src/store/entry.ts b/src/renderer/src/store/entry.ts index 7fdc2fd7c..a9475f094 100644 --- a/src/renderer/src/store/entry.ts +++ b/src/renderer/src/store/entry.ts @@ -10,7 +10,9 @@ import { persist } from "zustand/middleware" import { unreadActions } from "./unread" import { zustandStorage } from "./utils/helper" -type EntriesIdTable = Record> +type FeedId = string +type EntryId = string +type EntriesIdTable = Record interface EntryState { entries: EntriesIdTable @@ -29,9 +31,14 @@ interface EntryActions { }) => Promise> upsert: (feedId: string, entry: EntryModel) => void optimisticUpdate: (entryId: string, changed: Partial) => void + optimisticUpdateManyByFeedId: ( + feedId: string, + changed: Partial + ) => void optimisticUpdateAll: (changed: Partial) => void getFlattenMapEntries: () => Record markRead: (feedId: string, entryId: string, read: boolean) => void + markReadByFeedId: (feedId: string) => void } export const useEntryStore = create( @@ -90,7 +97,21 @@ export const useEntryStore = create( }), ) }, - optimisticUpdateAll(changed: Partial) { + optimisticUpdateManyByFeedId(feedId, changed) { + set((state) => + produce(state, (draft) => { + const ids = draft.entries[feedId] + if (!ids) return + + ids.forEach((entryId) => { + Object.assign(draft.flatMapEntries[entryId], changed) + }) + + return draft + }), + ) + }, + optimisticUpdateAll(changed) { set((state) => produce(state, (draft) => { for (const entry of Object.values(draft.flatMapEntries)) { @@ -100,14 +121,13 @@ export const useEntryStore = create( }), ) }, - upsert(feedId: string, entry: EntryModel) { set((state) => produce(state, (draft) => { if (!draft.entries[feedId]) { - draft.entries[feedId] = {} + draft.entries[feedId] = [] } - draft.entries[feedId][entry.entries.id] = entry + draft.entries[feedId].push(entry.entries.id) draft.flatMapEntries[entry.entries.id] = entry return draft }), @@ -120,6 +140,14 @@ export const useEntryStore = create( read, }) }, + markReadByFeedId: (feedId: string) => { + const state = get() + const entries = state.entries[feedId] || [] + entries.forEach((entryId) => { + entryActions.markRead(feedId, entryId, true) + }) + unreadActions.updateByFeedId(feedId, 0) + }, }), { name: "entry", @@ -136,7 +164,10 @@ export const entryActions = { } export const useEntriesByFeedId = (feedId: string) => - useEntryStore((state) => state.entries[feedId]) + useEntryStore((state) => { + const entryIds = state.entries[feedId] || [] + return entryIds.map((id) => state.flatMapEntries[id]) + }) export const useEntry = (entryId: string) => useEntryStore((state) => state.flatMapEntries[entryId]) diff --git a/src/renderer/src/store/subscription.ts b/src/renderer/src/store/subscription.ts index ede0d3500..ef84b2f77 100644 --- a/src/renderer/src/store/subscription.ts +++ b/src/renderer/src/store/subscription.ts @@ -6,6 +6,8 @@ import { omit } from "lodash-es" import { create } from "zustand" import { persist } from "zustand/middleware" +import { entryActions } from "./entry" +import { unreadActions } from "./unread" import { zustandStorage } from "./utils/helper" type FeedId = string @@ -15,10 +17,11 @@ interface SubscriptionState { interface SubscriptionActions { upsert: (feedId: FeedId, subscription: SubscriptionModel) => void fetchByView: (view?: FeedViewType) => Promise + markReadByView: (view?: FeedViewType) => void } export const useSubscriptionStore = create( persist( - (set) => ({ + (set, get) => ({ data: {}, async fetchByView(view) { @@ -45,6 +48,15 @@ export const useSubscriptionStore = create( }), ) }, + markReadByView(view) { + const state = get() + for (const feedId in state.data) { + if (state.data[feedId].view === view) { + unreadActions.updateByFeedId(feedId, 0) + entryActions.optimisticUpdateManyByFeedId(feedId, { read: true }) + } + } + }, }), { name: "subscription", @@ -56,3 +68,9 @@ export const useSubscriptionStore = create( export const subscriptionActions = { ...omit(useSubscriptionStore.getState(), ["data"]), } + +Object.assign(window, { + __subscription() { + return useSubscriptionStore.getState() + }, +})