fix: discover search update

Signed-off-by: Innei <i@innei.in>
This commit is contained in:
Innei 2024-10-11 21:29:41 +08:00
parent 3608bfb66e
commit baaa7cd90b
No known key found for this signature in database
GPG Key ID: 0F62D33977F021F7
5 changed files with 86 additions and 61 deletions

View File

@ -145,9 +145,15 @@ export function DiscoverForm({ type = "search" }: { type?: string }) {
jotaiStore.set(
discoverSearchDataAtom,
produce(currentData, (draft) => {
const sub = draft.find(
(i) => i.feed?.id === item.feed?.id || i.list?.id === item.list?.id,
)
const sub = draft.find((i) => {
if (item.feed) {
return i.feed?.id === item.feed.id
}
if (item.list) {
return i.list?.id === item.list.id
}
return false
})
if (!sub) return
sub.isSubscribed = true
sub.subscriptionCount = -~(sub.subscriptionCount as number)

View File

@ -1,5 +1,5 @@
import { useWheel } from "@use-gesture/react"
import { AnimatePresence, easeOut } from "framer-motion"
import { easeOut } from "framer-motion"
import type { FC, PropsWithChildren } from "react"
import { useState } from "react"
import { useHotkeys } from "react-hotkeys-hook"
@ -48,40 +48,38 @@ export const Component = () => {
}
return (
<AnimatePresence mode="popLayout">
<AppLayoutGridContainerProvider>
<EntryGridContainer showEntryContent={showEntryContent} wideMode={wideMode}>
{wideMode && (
// Close button
<ActionButton
className={cn(
"absolute left-3 top-3 z-10 duration-200",
shouldHeaderPaddingLeft
? "left-[calc(theme(width.3)+theme(width.feed-col))]"
: "left-3",
)}
tooltip="Close"
shortcut="Escape"
disableTriggerShortcut
onClick={() => navigate({ entryId: null })}
>
<i className="i-mgc-close-cute-re size-5" />
</ActionButton>
)}
<AppLayoutGridContainerProvider>
<EntryGridContainer showEntryContent={showEntryContent} wideMode={wideMode}>
{wideMode && (
// Close button
<ActionButton
className={cn(
"absolute left-3 top-3 z-10 duration-200",
shouldHeaderPaddingLeft
? "left-[calc(theme(width.3)+theme(width.feed-col))]"
: "left-3",
)}
tooltip="Close"
shortcut="Escape"
disableTriggerShortcut
onClick={() => navigate({ entryId: null })}
>
<i className="i-mgc-close-cute-re size-5" />
</ActionButton>
)}
<EntryContent
entryId={realEntryId}
classNames={{
header: shouldHeaderPaddingLeft
? "ml-[calc(theme(width.feed-col)+theme(width.8))]"
: wideMode
? "ml-8"
: "",
}}
/>
</EntryGridContainer>
</AppLayoutGridContainerProvider>
</AnimatePresence>
<EntryContent
entryId={realEntryId}
classNames={{
header: shouldHeaderPaddingLeft
? "ml-[calc(theme(width.feed-col)+theme(width.8))]"
: wideMode
? "ml-8"
: "",
}}
/>
</EntryGridContainer>
</AppLayoutGridContainerProvider>
)
}

View File

@ -35,7 +35,4 @@ export const AppLayoutGridContainerProvider: FC<PropsWithChildren> = ({ children
)
}
export const useAppLayoutGridContainerWidth = () => {
const width = useContext(AppLayoutGridContainerWidthContext)
return width
}
export const useAppLayoutGridContainerWidth = () => useContext(AppLayoutGridContainerWidthContext)

View File

@ -42,7 +42,11 @@ export const useFolderFeedsByFeedId = ({ feedId, view }: { feedId?: string; view
})
export const useListSubscriptionCount = () =>
useSubscriptionStore((state) => Object.values(state.data).filter((s) => !!s.listId).length)
useSubscriptionStore(
(state) =>
Object.values(state.data).filter((s) => !!s.listId && state.subscriptionIdSet.has(s.listId))
.length,
)
export const useInboxSubscriptionCount = () =>
useSubscriptionStore(
@ -55,6 +59,8 @@ export const useInboxSubscriptionCount = () =>
export const useFeedSubscriptionCount = () =>
useSubscriptionStore(
(state) =>
// FIXME: Backend data compatibility
Object.values(state.data).filter((s) => !!s.feedId && !s.listId && !s.inboxId).length,
Object.values(state.data).filter(
// FIXME: Backend data compatibility
(s) => !!s.feedId && !s.listId && !s.inboxId && state.subscriptionIdSet.has(s.feedId),
).length,
)

View File

@ -40,6 +40,10 @@ interface SubscriptionState {
* Value: Record<string, boolean>
*/
categoryOpenStateByView: Record<FeedViewType, Record<string, boolean>>
/**
* Store the subscription ids that current user followed.
*/
subscriptionIdSet: Set<string>
}
function morphResponseData(data: SubscriptionModel[]): SubscriptionFlatModel[] {
@ -86,6 +90,7 @@ export const useSubscriptionStore = createZustandStore<SubscriptionState>("subsc
data: {},
feedIdByView: { ...emptyDataIdByView },
categoryOpenStateByView: { ...emptyCategoryOpenStateByView },
subscriptionIdSet: new Set<string>(),
}))
const set = useSubscriptionStore.setState
@ -96,8 +101,24 @@ type MarkReadFilter = {
startTime: number
endTime: number
}
let subscribeOnce = false
class SubscriptionActions {
constructor() {
if (subscribeOnce) return
subscribeOnce = true
// autorun
useSubscriptionStore.subscribe((next, prev) => {
if (next.feedIdByView !== prev.feedIdByView) {
const allSubscriptionIds = Object.values(next.feedIdByView).flat()
set((state) => {
return {
...state,
subscriptionIdSet: new Set(allSubscriptionIds),
}
})
}
})
}
async fetchByView(view?: FeedViewType) {
const res = await apiClient.subscriptions.$get({
query: {
@ -287,22 +308,19 @@ class SubscriptionActions {
},
}),
async () => {
set((state) =>
produce(state, (state) => {
Object.keys(state.data).forEach((id) => {
if (idSet.has(id)) {
const subscription = state.data[id]
const feed = getFeedById(subscription.feedId)
if (!feed || feed.type !== "feed") return
const { siteUrl } = feed
if (!siteUrl) return
const parsed = parse(siteUrl)
subscription.category = null
// The logic for removing Category here is to use domain as the default category name.
parsed.domain &&
(subscription.defaultCategory = capitalizeFirstLetter(parsed.domain))
}
})
immerSet((state) =>
Object.keys(state.data).forEach((id) => {
if (idSet.has(id)) {
const subscription = state.data[id]
const feed = getFeedById(subscription.feedId)
if (!feed || feed.type !== "feed") return
const { siteUrl } = feed
if (!siteUrl) return
const parsed = parse(siteUrl)
subscription.category = null
// The logic for removing Category here is to use domain as the default category name.
parsed.domain && (subscription.defaultCategory = capitalizeFirstLetter(parsed.domain))
}
}),
)
const { data } = get()