feat: custom feed title (#300)
* feat: custom feed title * fix: use type button * refactor: do not override original feed title
This commit is contained in:
parent
6ce06be58d
commit
501e2f44c1
|
|
@ -2790,6 +2790,7 @@ declare const _routes: hono_hono_base.HonoBase<Env, {
|
|||
json: {
|
||||
view: number;
|
||||
url: string;
|
||||
title?: string | null | undefined;
|
||||
category?: string | null | undefined;
|
||||
isPrivate?: boolean | undefined;
|
||||
};
|
||||
|
|
@ -2818,6 +2819,7 @@ declare const _routes: hono_hono_base.HonoBase<Env, {
|
|||
json: {
|
||||
view: number;
|
||||
feedId: string;
|
||||
title?: string | null | undefined;
|
||||
category?: string | null | undefined;
|
||||
isPrivate?: boolean | undefined;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import {
|
|||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@renderer/components/ui/form"
|
||||
import { Input } from "@renderer/components/ui/input"
|
||||
import { LoadingCircle } from "@renderer/components/ui/loading"
|
||||
import { useCurrentModal } from "@renderer/components/ui/modal"
|
||||
import { Switch } from "@renderer/components/ui/switch"
|
||||
|
|
@ -38,6 +39,7 @@ const formSchema = z.object({
|
|||
view: z.string(),
|
||||
category: z.string().nullable().optional(),
|
||||
isPrivate: z.boolean().optional(),
|
||||
title: z.string().optional(),
|
||||
})
|
||||
|
||||
const defaultValue = { view: FeedViewType.Articles.toString() } as z.infer<
|
||||
|
|
@ -142,6 +144,7 @@ const FeedInnerForm = ({
|
|||
form.setValue("view", `${subscription?.view}`)
|
||||
subscription?.category && form.setValue("category", subscription.category)
|
||||
form.setValue("isPrivate", subscription?.isPrivate || false)
|
||||
form.setValue("title", subscription?.title || "")
|
||||
}
|
||||
}, [subscription])
|
||||
|
||||
|
|
@ -152,6 +155,7 @@ const FeedInnerForm = ({
|
|||
view: Number.parseInt(values.view),
|
||||
category: values.category,
|
||||
isPrivate: values.isPrivate,
|
||||
title: values.title,
|
||||
...(isSubscribed && { feedId: feed.id }),
|
||||
}
|
||||
const $method = isSubscribed ?
|
||||
|
|
@ -266,6 +270,24 @@ const FeedInnerForm = ({
|
|||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="title"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<div>
|
||||
<FormLabel>Tile</FormLabel>
|
||||
<FormDescription>
|
||||
Custom title for this Feed. Leave empty to use the default.
|
||||
</FormDescription>
|
||||
</div>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="category"
|
||||
|
|
@ -325,6 +347,7 @@ const FeedInnerForm = ({
|
|||
<div className="flex flex-1 items-end justify-end gap-4">
|
||||
{isSubscribed && (
|
||||
<Button
|
||||
type="button"
|
||||
ref={buttonRef}
|
||||
variant="text"
|
||||
isLoading={deleteSubscription.isPending}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { useAsRead } from "@renderer/hooks/biz/useAsRead"
|
|||
import { cn } from "@renderer/lib/utils"
|
||||
import { EntryTranslation } from "@renderer/modules/entry-column/translation"
|
||||
import { useEntry } from "@renderer/store/entry/hooks"
|
||||
import { useFeedById } from "@renderer/store/feed"
|
||||
import { getPreferredTitle, useFeedById } from "@renderer/store/feed"
|
||||
import dayjs from "dayjs"
|
||||
|
||||
import { StarIcon } from "../star-icon"
|
||||
|
|
@ -63,7 +63,7 @@ export function GridItem({
|
|||
entry={entry.entries}
|
||||
size={18}
|
||||
/>
|
||||
<span className="min-w-0 truncate">{feeds?.title}</span>
|
||||
<span className="min-w-0 truncate">{getPreferredTitle(feeds)}</span>
|
||||
<span className="text-zinc-500">·</span>
|
||||
<span className="text-zinc-500">
|
||||
{dayjs
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import { cn, isSafari } from "@renderer/lib/utils"
|
|||
import { EntryTranslation } from "@renderer/modules/entry-column/translation"
|
||||
import { Queries } from "@renderer/queries"
|
||||
import { useEntry } from "@renderer/store/entry/hooks"
|
||||
import { useFeedById } from "@renderer/store/feed"
|
||||
import { getPreferredTitle, useFeedById } from "@renderer/store/feed"
|
||||
import { useDebounceCallback } from "usehooks-ts"
|
||||
|
||||
import { ReactVirtuosoItemPlaceholder } from "../../../components/ui/placeholder"
|
||||
|
|
@ -82,7 +82,7 @@ export function ListItem({
|
|||
entry.collections && "text-zinc-600 dark:text-zinc-500",
|
||||
)}
|
||||
>
|
||||
<span className="truncate">{feed.title}</span>
|
||||
<span className="truncate">{getPreferredTitle(feed)}</span>
|
||||
<span>·</span>
|
||||
<span className="shrink-0">
|
||||
{!!displayTime && <RelativeTime date={displayTime} />}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ import {
|
|||
} from "@renderer/providers/wrapped-element-provider"
|
||||
import { Queries } from "@renderer/queries"
|
||||
import { useEntry, useEntryReadHistory } from "@renderer/store/entry"
|
||||
import { useFeedById, useFeedHeaderTitle } from "@renderer/store/feed"
|
||||
import { getPreferredTitle, useFeedById, useFeedHeaderTitle } from "@renderer/store/feed"
|
||||
import type { FallbackRender } from "@sentry/react"
|
||||
import { ErrorBoundary } from "@sentry/react"
|
||||
import type { FC } from "react"
|
||||
|
|
@ -190,7 +190,7 @@ export const EntryContentRender: Component<{ entryId: string }> = ({
|
|||
/>
|
||||
</div>
|
||||
<div className="mt-2 text-[13px] font-medium text-zinc-500">
|
||||
{feed?.title}
|
||||
{getPreferredTitle(feed)}
|
||||
</div>
|
||||
<div className="flex items-center gap-2 text-[13px] text-zinc-500">
|
||||
{entry.entries.publishedAt &&
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import { nextFrame } from "@renderer/lib/dom"
|
|||
import { getNewIssueUrl } from "@renderer/lib/issues"
|
||||
import { showNativeMenu } from "@renderer/lib/native-menu"
|
||||
import { cn } from "@renderer/lib/utils"
|
||||
import { useFeedById } from "@renderer/store/feed"
|
||||
import { getPreferredTitle, useFeedById } from "@renderer/store/feed"
|
||||
import { useSubscriptionByFeedId } from "@renderer/store/subscription"
|
||||
import { useFeedUnreadStore } from "@renderer/store/unread"
|
||||
import { WEB_URL } from "@shared/constants"
|
||||
|
|
@ -124,7 +124,7 @@ const FeedItemImpl = ({
|
|||
(feedUnread ? "font-bold" : "font-medium opacity-70"),
|
||||
)}
|
||||
>
|
||||
{feed.title}
|
||||
{getPreferredTitle(feed)}
|
||||
</div>
|
||||
{isOwned && (
|
||||
<Tooltip delayDuration={300}>
|
||||
|
|
|
|||
|
|
@ -6,8 +6,10 @@ import {
|
|||
} from "@renderer/constants"
|
||||
import { useRouteParms } from "@renderer/hooks/biz/useRouteParams"
|
||||
import type { FeedModel } from "@renderer/models"
|
||||
import { useMemo } from "react"
|
||||
import { useShallow } from "zustand/react/shallow"
|
||||
|
||||
import { getSubscriptionByFeedId } from "../subscription"
|
||||
import { useFeedStore } from "./store"
|
||||
import type { FeedQueryParams } from "./types"
|
||||
|
||||
|
|
@ -38,6 +40,10 @@ export const useFeedHeaderTitle = () => {
|
|||
const { feedId: currentFeedId, view } = useRouteParms()
|
||||
|
||||
const feedTitle = useFeedByIdSelector(currentFeedId, (feed) => feed.title)
|
||||
const subscriptionTitle = useMemo(
|
||||
() => currentFeedId ? getSubscriptionByFeedId(currentFeedId)?.title ?? "" : "",
|
||||
[currentFeedId],
|
||||
)
|
||||
|
||||
switch (currentFeedId) {
|
||||
case ROUTE_FEED_PENDING: {
|
||||
|
|
@ -50,7 +56,7 @@ export const useFeedHeaderTitle = () => {
|
|||
if (currentFeedId?.startsWith(ROUTE_FEED_IN_FOLDER)) {
|
||||
return currentFeedId.replace(ROUTE_FEED_IN_FOLDER, "")
|
||||
}
|
||||
return feedTitle
|
||||
return subscriptionTitle || feedTitle
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { FeedService } from "@renderer/services"
|
|||
import { produce } from "immer"
|
||||
import { nanoid } from "nanoid"
|
||||
|
||||
import { getSubscriptionByFeedId } from "../subscription"
|
||||
import { createZustandStore, doMutationAndTransaction } from "../utils/helper"
|
||||
import type { FeedQueryParams, FeedState } from "./types"
|
||||
|
||||
|
|
@ -100,3 +101,12 @@ export const feedActions = new FeedActions()
|
|||
|
||||
export const getFeedById = (feedId: string): Nullable<FeedModel> =>
|
||||
useFeedStore.getState().feeds[feedId]
|
||||
|
||||
export const getPreferredTitle = (feed?: FeedModel | null) => {
|
||||
if (!feed?.id) {
|
||||
return feed?.title
|
||||
}
|
||||
|
||||
const subscription = getSubscriptionByFeedId(feed.id)
|
||||
return subscription?.title || feed.title
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue