From ed95fb6b239b9cbbae54f6eb3ff8e6a4d8053538 Mon Sep 17 00:00:00 2001 From: Stephen Zhou <38493346+hyoban@users.noreply.github.com> Date: Tue, 13 May 2025 15:34:29 +0800 Subject: [PATCH] feat: show rsshub error message --- .../src/components/common/ErrorTooltip.tsx | 45 ++++++++++++ .../src/modules/timeline-column/FeedItem.tsx | 29 ++------ .../(main)/(layer)/(subview)/rsshub/index.tsx | 70 ++++++++++++------- locales/errors/en.json | 1 + locales/settings/en.json | 2 + packages/internal/shared/src/hono.ts | 44 ++++++++++++ 6 files changed, 142 insertions(+), 49 deletions(-) create mode 100644 apps/desktop/layer/renderer/src/components/common/ErrorTooltip.tsx diff --git a/apps/desktop/layer/renderer/src/components/common/ErrorTooltip.tsx b/apps/desktop/layer/renderer/src/components/common/ErrorTooltip.tsx new file mode 100644 index 000000000..2e5031649 --- /dev/null +++ b/apps/desktop/layer/renderer/src/components/common/ErrorTooltip.tsx @@ -0,0 +1,45 @@ +import { + Tooltip, + TooltipContent, + TooltipPortal, + TooltipTrigger, +} from "@follow/components/ui/tooltip/index.js" +import dayjs from "dayjs" +import { useTranslation } from "react-i18next" + +export function ErrorTooltip({ + errorAt, + errorMessage, + children, + showWhenError = false, +}: { + errorMessage?: string | null + errorAt?: string | null + children: React.ReactNode + showWhenError?: boolean +}) { + const { t } = useTranslation() + if (!errorAt || !errorMessage) { + return showWhenError ? children : null + } + return ( + + {children} + + +
+ + {t("feed_item.error_since")}{" "} + {dayjs.duration(dayjs(errorAt).diff(dayjs(), "minute"), "minute").humanize(true)} +
+ {!!errorMessage && ( +
+ + {errorMessage} +
+ )} +
+
+
+ ) +} diff --git a/apps/desktop/layer/renderer/src/modules/timeline-column/FeedItem.tsx b/apps/desktop/layer/renderer/src/modules/timeline-column/FeedItem.tsx index 4a54bb652..f269283fd 100644 --- a/apps/desktop/layer/renderer/src/modules/timeline-column/FeedItem.tsx +++ b/apps/desktop/layer/renderer/src/modules/timeline-column/FeedItem.tsx @@ -11,13 +11,13 @@ import { EllipsisHorizontalTextWithTooltip } from "@follow/components/ui/typogra import type { FeedViewType } from "@follow/constants" import { nextFrame } from "@follow/utils/dom" import { cn, isKeyForMultiSelectPressed } from "@follow/utils/utils" -import dayjs from "dayjs" import { createElement, memo, use, useCallback, useState } from "react" import { useTranslation } from "react-i18next" import { MenuItemSeparator, MenuItemText, useShowContextMenu } from "~/atoms/context-menu" import { getMainContainerElement } from "~/atoms/dom" import { useGeneralSettingKey } from "~/atoms/settings/general" +import { ErrorTooltip } from "~/components/common/ErrorTooltip" import { useFeedActions, useInboxActions, useListActions } from "~/hooks/biz/useFeedActions" import { useFollow } from "~/hooks/biz/useFollow" import { useNavigateEntry } from "~/hooks/biz/useNavigateEntry" @@ -187,29 +187,10 @@ const FeedItemImpl = ({ view, feedId, className, isPreview }: FeedItemProps) =>
- {isFeed && feed.errorAt && ( - - - - - - -
- - {t("feed_item.error_since")}{" "} - {dayjs - .duration(dayjs(feed.errorAt).diff(dayjs(), "minute"), "minute") - .humanize(true)} -
- {!!feed.errorMessage && ( -
- - {feed.errorMessage} -
- )} -
-
-
+ {isFeed && ( + + + )} {subscription?.isPrivate && ( diff --git a/apps/desktop/layer/renderer/src/pages/(main)/(layer)/(subview)/rsshub/index.tsx b/apps/desktop/layer/renderer/src/pages/(main)/(layer)/(subview)/rsshub/index.tsx index bf2f07167..b7669286a 100644 --- a/apps/desktop/layer/renderer/src/pages/(main)/(layer)/(subview)/rsshub/index.tsx +++ b/apps/desktop/layer/renderer/src/pages/(main)/(layer)/(subview)/rsshub/index.tsx @@ -14,6 +14,7 @@ import { useTranslation } from "react-i18next" import RSSHubIconUrl from "~/assets/rsshub-icon.png?url" import { whoami } from "~/atoms/user" +import { ErrorTooltip } from "~/components/common/ErrorTooltip" import { useModalStack } from "~/components/ui/modal/stacked/hooks" import { useAuthQuery } from "~/hooks/common" import { useSubViewTitle } from "~/modules/app-layout/subview/hooks" @@ -129,6 +130,13 @@ function List({ data }: { data?: RSSHubModel[] }) { return 1 } + if (a.errorMessage && !b.errorMessage) { + return 1 + } + if (!a.errorMessage && b.errorMessage) { + return -1 + } + const loadA = Math.min((a.userCount ?? 0) / (a.userLimit ?? Infinity), 1) const loadB = Math.min((b.userCount ?? 0) / (b.userLimit ?? Infinity), 1) @@ -191,31 +199,7 @@ function List({ data }: { data?: RSSHubModel[] }) {
- + {me?.id === instance.ownerUserId && ( + + ) +} diff --git a/locales/errors/en.json b/locales/errors/en.json index d06890517..1d1cab113 100644 --- a/locales/errors/en.json +++ b/locales/errors/en.json @@ -64,6 +64,7 @@ "13004": "RSSHub user limit exceeded", "13005": "RSSHub purchase not found", "13006": "RSSHub config invalid", + "13007": "This RSSHub instance is unavailable currently", "14000": "Invalid file", "14001": "File too large", "14002": "Upload failed" diff --git a/locales/settings/en.json b/locales/settings/en.json index ec2722555..dd92d048a 100644 --- a/locales/settings/en.json +++ b/locales/settings/en.json @@ -393,10 +393,12 @@ "rsshub.table.description": "Description", "rsshub.table.edit": "Edit", "rsshub.table.inuse": "In Use", + "rsshub.table.limit_reached": "Limit Reached", "rsshub.table.official": "Official", "rsshub.table.owner": "Owner", "rsshub.table.price": "Monthly Price", "rsshub.table.private": "Private", + "rsshub.table.unavailable": "Unavailable", "rsshub.table.unlimited": "Unlimited", "rsshub.table.use": "Use", "rsshub.table.userCount": "User Count", diff --git a/packages/internal/shared/src/hono.ts b/packages/internal/shared/src/hono.ts index 549c98987..6da66015e 100644 --- a/packages/internal/shared/src/hono.ts +++ b/packages/internal/shared/src/hono.ts @@ -5211,6 +5211,40 @@ declare const rsshub: drizzle_orm_pg_core.PgTableWithColumns<{ identity: undefined; generated: undefined; }, {}, {}>; + errorMessage: drizzle_orm_pg_core.PgColumn<{ + name: "error_message"; + tableName: "rsshub"; + dataType: "string"; + columnType: "PgText"; + data: string; + driverParam: string; + notNull: false; + hasDefault: false; + isPrimaryKey: false; + isAutoincrement: false; + hasRuntimeDefault: false; + enumValues: [string, ...string[]]; + baseColumn: never; + identity: undefined; + generated: undefined; + }, {}, {}>; + errorAt: drizzle_orm_pg_core.PgColumn<{ + name: "error_at"; + tableName: "rsshub"; + dataType: "date"; + columnType: "PgTimestamp"; + data: Date; + driverParam: string; + notNull: false; + hasDefault: false; + isPrimaryKey: false; + isAutoincrement: false; + hasRuntimeDefault: false; + enumValues: undefined; + baseColumn: never; + identity: undefined; + generated: undefined; + }, {}, {}>; }; dialect: "pg"; }>; @@ -5222,9 +5256,13 @@ declare const rsshubOpenAPISchema: zod.ZodObject<{ price: zod.ZodNumber; description: zod.ZodNullable; userLimit: zod.ZodNullable; + errorMessage: zod.ZodNullable; + errorAt: zod.ZodNullable; }, zod.UnknownKeysParam, zod.ZodTypeAny, { id: string; description: string | null; + errorMessage: string | null; + errorAt: string | null; ownerUserId: string; baseUrl: string; accessKey: string | null; @@ -5233,6 +5271,8 @@ declare const rsshubOpenAPISchema: zod.ZodObject<{ }, { id: string; description: string | null; + errorMessage: string | null; + errorAt: string | null; ownerUserId: string; baseUrl: string; accessKey: string | null; @@ -16844,6 +16884,8 @@ declare const _routes: hono_hono_base.HonoBase