fix: collection bug

Signed-off-by: Innei <i@innei.in>
This commit is contained in:
Innei 2024-07-06 19:10:29 +08:00
parent 58b55e3c32
commit a4e6709c46
No known key found for this signature in database
GPG Key ID: 0F62D33977F021F7
4 changed files with 82 additions and 74 deletions

View File

@ -1,5 +1,4 @@
import { getOS } from "@renderer/lib/utils"
import { memoize } from "lodash-es"
import type { FC } from "react"
const SpecialKeys = {
@ -23,11 +22,10 @@ const SpecialKeys = {
},
}
const os = memoize(getOS)
export const Kbd: FC<{
children: string
}> = ({ children }) => {
const specialKeys = SpecialKeys[os()]
const specialKeys = SpecialKeys[getOS()]
let key = children
if (children.toLowerCase() in specialKeys) {
key = specialKeys[children.toLowerCase()]

View File

@ -1,5 +1,6 @@
import type { ClassValue } from "clsx"
import { clsx } from "clsx"
import { memoize } from "lodash-es"
import { twMerge } from "tailwind-merge"
import { FEED_COLLECTION_LIST, levels } from "./constants"
@ -42,7 +43,7 @@ export function getEntriesParams({
}
export type OS = "macOS" | "iOS" | "Windows" | "Android" | "Linux" | ""
export function getOS(): OS {
export const getOS = memoize((): OS => {
const { userAgent } = window.navigator,
{ platform } = window.navigator,
macosPlatforms = ["Macintosh", "MacIntel", "MacPPC", "Mac68K"],
@ -63,7 +64,7 @@ export function getOS(): OS {
}
return os as OS
}
})
// eslint-disable-next-line no-control-regex
export const isASCII = (str) => /^[\u0000-\u007F]*$/.test(str)
@ -74,7 +75,13 @@ export const isBizId = (id) => {
// id is uuid or snowflake
// 0. check is uuid
if (id.length === 36 && id[8] === "-" && id[13] === "-" && id[18] === "-" && id[23] === "-") {
if (
id.length === 36 &&
id[8] === "-" &&
id[13] === "-" &&
id[18] === "-" &&
id[23] === "-"
) {
return true
}
@ -112,7 +119,8 @@ export function formatXml(xml: string, indent = 4) {
return formatted.trim()
}
export const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))
export const sleep = (ms: number) =>
new Promise((resolve) => setTimeout(resolve, ms))
export const capitalizeFirstLetter = (string: string) =>
string.charAt(0).toUpperCase() + string.slice(1)

View File

@ -48,7 +48,6 @@ import {
useCallback,
useEffect,
useLayoutEffect,
useMemo,
useRef,
useState,
} from "react"
@ -184,7 +183,7 @@ const ListHeader: FC<{
}, [feedId, folderIds, routerParams])
const headerTitle = useFeedHeaderTitle()
const os = useMemo(getOS, [])
const os = getOS()
const titleAtBottom = window.electron && os === "macOS"
const titleInfo = (
@ -222,70 +221,71 @@ const ListHeader: FC<{
)}
>
{!titleAtBottom && titleInfo}
{!isInCollectionList && (
<div
className="relative z-[1] flex items-center gap-1 self-baseline text-zinc-500"
onClick={(e) => e.stopPropagation()}
>
{views[view].wideMode &&
entryId &&
entryId !== ROUTE_ENTRY_PENDING && (
<>
<EntryHeader view={view} entryId={entryId} />
<DividerVertical className="w-px" />
</>
)}
{feed?.ownerUserId === user?.id && isBizId(routerParams.feedId) && (
<ActionButton
tooltip="Refresh"
// shortcut={shortcuts.entries.toggleUnreadOnly.key}
onClick={() => {
refreshFeed()
}}
>
<i
className={cn(
"i-mgc-refresh-2-cute-re",
isPending && "animate-spin",
)}
/>
</ActionButton>
)}
<div
className={cn("relative z-[1] flex items-center gap-1 self-baseline text-zinc-500", isInCollectionList && "pointer-events-none opacity-0",
)}
onClick={(e) => e.stopPropagation()}
>
{views[view].wideMode &&
entryId &&
entryId !== ROUTE_ENTRY_PENDING && (
<>
<EntryHeader view={view} entryId={entryId} />
<DividerVertical className="w-px" />
</>
)}
{feed?.ownerUserId === user?.id && isBizId(routerParams.feedId) && (
<ActionButton
tooltip={unreadOnly ? "Unread Only" : "All"}
shortcut={shortcuts.entries.toggleUnreadOnly.key}
onClick={() => setGeneralSetting("unreadOnly", !unreadOnly)}
tooltip="Refresh"
// shortcut={shortcuts.entries.toggleUnreadOnly.key}
onClick={() => {
refreshFeed()
}}
>
{unreadOnly ? (
<i className="i-mgc-round-cute-fi" />
) : (
<i className="i-mgc-round-cute-re" />
)}
<i
className={cn(
"i-mgc-refresh-2-cute-re",
isPending && "animate-spin",
)}
/>
</ActionButton>
<Popover open={markPopoverOpen} onOpenChange={setMarkPopoverOpen}>
<PopoverTrigger asChild>
<ActionButton
shortcut={shortcuts.entries.markAllAsRead.key}
tooltip="Mark All as Read"
>
<i className="i-mgc-check-circle-cute-re" />
</ActionButton>
</PopoverTrigger>
<PopoverContent className="flex w-fit flex-col items-center justify-center gap-3 text-[0.94rem] font-medium">
<div>Mark all as read?</div>
<div className="space-x-4">
<PopoverClose>
<StyledButton variant="outline">Cancel</StyledButton>
</PopoverClose>
{/* TODO */}
<StyledButton onClick={handleMarkAllAsRead}>
Confirm
</StyledButton>
</div>
</PopoverContent>
</Popover>
</div>
)}
)}
<ActionButton
tooltip={unreadOnly ? "Unread Only" : "All"}
shortcut={shortcuts.entries.toggleUnreadOnly.key}
onClick={() => setGeneralSetting("unreadOnly", !unreadOnly)}
>
{unreadOnly ? (
<i className="i-mgc-round-cute-fi" />
) : (
<i className="i-mgc-round-cute-re" />
)}
</ActionButton>
<Popover open={markPopoverOpen} onOpenChange={setMarkPopoverOpen}>
<PopoverTrigger asChild>
<ActionButton
shortcut={shortcuts.entries.markAllAsRead.key}
tooltip="Mark All as Read"
>
<i className="i-mgc-check-circle-cute-re" />
</ActionButton>
</PopoverTrigger>
<PopoverContent className="flex w-fit flex-col items-center justify-center gap-3 text-[0.94rem] font-medium">
<div>Mark all as read?</div>
<div className="space-x-4">
<PopoverClose>
<StyledButton variant="outline">Cancel</StyledButton>
</PopoverClose>
{/* TODO */}
<StyledButton onClick={handleMarkAllAsRead}>
Confirm
</StyledButton>
</div>
</PopoverContent>
</Popover>
</div>
</div>
{titleAtBottom && titleInfo}
</div>

View File

@ -1,5 +1,5 @@
import { apiClient } from "@renderer/lib/api-fetch"
import { ROUTE_FEED_IN_FOLDER } from "@renderer/lib/constants"
import { FEED_COLLECTION_LIST, ROUTE_FEED_IN_FOLDER } from "@renderer/lib/constants"
import { FeedViewType } from "@renderer/lib/enum"
import { capitalizeFirstLetter } from "@renderer/lib/utils"
import type { SubscriptionModel } from "@renderer/models"
@ -156,12 +156,14 @@ export const useSubscriptionByFeedId = (feedId: FeedId) =>
useSubscriptionStore((state) => state.data[feedId])
export const useFolderFeedsByFeedId = (feedId?: string) =>
useSubscriptionStore((state) => {
if (typeof feedId !== "string") return
useSubscriptionStore((state): string[] => {
if (typeof feedId !== "string") return []
if (feedId === FEED_COLLECTION_LIST) { return [feedId] }
if (!feedId.startsWith(ROUTE_FEED_IN_FOLDER)) {
return
return []
}
const folderName = feedId.replace(ROUTE_FEED_IN_FOLDER, "")
const feedIds: string[] = []
for (const feedId in state.data) {