fix: read all (#37)

Signed-off-by: Innei <i@innei.in>
This commit is contained in:
Innei 2024-06-04 19:41:07 +08:00 committed by GitHub
parent ce7b4ab0ab
commit 29176e8695
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 69 additions and 9 deletions

View File

@ -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])

View File

@ -10,7 +10,9 @@ import { persist } from "zustand/middleware"
import { unreadActions } from "./unread"
import { zustandStorage } from "./utils/helper"
type EntriesIdTable = Record<string, Record<string, EntryModel>>
type FeedId = string
type EntryId = string
type EntriesIdTable = Record<FeedId, EntryId[]>
interface EntryState {
entries: EntriesIdTable
@ -29,9 +31,14 @@ interface EntryActions {
}) => Promise<InferResponseType<typeof apiClient.entries.$post>>
upsert: (feedId: string, entry: EntryModel) => void
optimisticUpdate: (entryId: string, changed: Partial<EntryModel>) => void
optimisticUpdateManyByFeedId: (
feedId: string,
changed: Partial<EntryModel>
) => void
optimisticUpdateAll: (changed: Partial<EntryModel>) => void
getFlattenMapEntries: () => Record<string, EntryModel>
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<EntryModel>) {
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])

View File

@ -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<SubscriptionModel[]>
markReadByView: (view?: FeedViewType) => void
}
export const useSubscriptionStore = create(
persist<SubscriptionState & SubscriptionActions>(
(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()
},
})