From 87ca20c04792590dfebe612aa38b2088c2bb9e04 Mon Sep 17 00:00:00 2001 From: twwu Date: Mon, 18 Nov 2024 11:54:51 +0800 Subject: [PATCH] feat: add version checking for GitHub releases and improve error handling --- .../plugins/install-plugin/hooks.ts | 18 +++++++++- .../plugin-detail-panel/detail-header.tsx | 36 +++++++++---------- .../components/plugins/plugin-item/action.tsx | 28 ++++++++------- .../components/plugins/plugin-item/index.tsx | 2 +- 4 files changed, 52 insertions(+), 32 deletions(-) diff --git a/web/app/components/plugins/install-plugin/hooks.ts b/web/app/components/plugins/install-plugin/hooks.ts index 8ad26985cd..50ed9ab085 100644 --- a/web/app/components/plugins/install-plugin/hooks.ts +++ b/web/app/components/plugins/install-plugin/hooks.ts @@ -2,6 +2,8 @@ import Toast from '@/app/components/base/toast' import { uploadGitHub } from '@/service/plugins' import { Octokit } from '@octokit/core' import { GITHUB_ACCESS_TOKEN } from '@/config' +import { compareVersion, getLatestVersion } from '@/utils/semver' +import type { GitHubRepoReleaseResponse } from '../types' export const useGitHubReleases = () => { const fetchReleases = async (owner: string, repo: string) => { @@ -37,7 +39,21 @@ export const useGitHubReleases = () => { } } - return { fetchReleases } + const checkForUpdates = (fetchedReleases: GitHubRepoReleaseResponse[], currentVersion: string) => { + if (fetchedReleases.length === 0) throw new Error('No releases found') + const versions = fetchedReleases.map(release => release.tag_name) + const latestVersion = getLatestVersion(versions) + let res = false + try { + res = compareVersion(latestVersion, currentVersion) === 1 + } + catch { + throw new Error('Failed to compare versions, please check the version format.') + } + return res + } + + return { fetchReleases, checkForUpdates } } export const useGitHubUpload = () => { diff --git a/web/app/components/plugins/plugin-detail-panel/detail-header.tsx b/web/app/components/plugins/plugin-detail-panel/detail-header.tsx index 024d5c2804..c28a091518 100644 --- a/web/app/components/plugins/plugin-detail-panel/detail-header.tsx +++ b/web/app/components/plugins/plugin-detail-panel/detail-header.tsx @@ -15,7 +15,6 @@ import Icon from '../card/base/card-icon' import Title from '../card/base/title' import OrgInfo from '../card/base/org-info' import { useGitHubReleases } from '../install-plugin/hooks' -import { compareVersion, getLatestVersion } from '@/utils/semver' import PluginVersionPicker from '@/app/components/plugins/update-plugin/plugin-version-picker' import UpdateFromMarketplace from '@/app/components/plugins/update-plugin/from-market-place' import OperationDropdown from '@/app/components/plugins/plugin-detail-panel/operation-dropdown' @@ -49,7 +48,7 @@ const DetailHeader = ({ }: Props) => { const { t } = useTranslation() const locale = useGetLanguage() - const { fetchReleases } = useGitHubReleases() + const { checkForUpdates, fetchReleases } = useGitHubReleases() const { setShowUpdatePluginModal } = useModalContext() const { @@ -72,14 +71,11 @@ const DetailHeader = ({ unique_identifier: latest_unique_identifier, }) const hasNewVersion = useMemo(() => { - if (isFromGitHub) - return latest_version !== version - if (isFromMarketplace) return !!latest_version && latest_version !== version return false - }, [isFromGitHub, isFromMarketplace, latest_version, version]) + }, [isFromMarketplace, latest_version, version]) const [isShowUpdateModal, { setTrue: showUpdateModal, @@ -94,11 +90,7 @@ const DetailHeader = ({ try { const fetchedReleases = await fetchReleases(author, name) - if (fetchedReleases.length === 0) - return - const versions = fetchedReleases.map(release => release.tag_name) - const latestVersion = getLatestVersion(versions) - if (compareVersion(latestVersion, version) === 1) { + if (checkForUpdates(fetchedReleases, meta!.version)) { setShowUpdatePluginModal({ onSaveCallback: () => { onUpdate() @@ -107,7 +99,7 @@ const DetailHeader = ({ type: PluginSource.github, github: { originalPackageInfo: { - id: installation_id, + id: detail.plugin_unique_identifier, repo: meta!.repo, version: meta!.version, package: meta!.package, @@ -124,11 +116,19 @@ const DetailHeader = ({ }) } } - catch { - Toast.notify({ - type: 'error', - message: 'Failed to compare versions', - }) + catch (error) { + if (error instanceof Error) { + Toast.notify({ + type: 'error', + message: error.message, + }) + } + else { + Toast.notify({ + type: 'error', + message: 'Failed to compare versions', + }) + } } } @@ -203,7 +203,7 @@ const DetailHeader = ({ /> } /> - {hasNewVersion && ( + {(hasNewVersion || isFromGitHub) && ( )} diff --git a/web/app/components/plugins/plugin-item/action.tsx b/web/app/components/plugins/plugin-item/action.tsx index 52c8c10309..773e42fdc9 100644 --- a/web/app/components/plugins/plugin-item/action.tsx +++ b/web/app/components/plugins/plugin-item/action.tsx @@ -11,7 +11,6 @@ import Tooltip from '../../base/tooltip' import Confirm from '../../base/confirm' import { uninstallPlugin } from '@/service/plugins' import { useGitHubReleases } from '../install-plugin/hooks' -import { compareVersion, getLatestVersion } from '@/utils/semver' import Toast from '@/app/components/base/toast' import { useModalContext } from '@/context/modal-context' import { useInvalidateInstalledPluginList } from '@/service/use-plugins' @@ -50,18 +49,14 @@ const Action: FC = ({ setTrue: showDeleting, setFalse: hideDeleting, }] = useBoolean(false) - const { fetchReleases } = useGitHubReleases() + const { checkForUpdates, fetchReleases } = useGitHubReleases() const { setShowUpdatePluginModal } = useModalContext() const invalidateInstalledPluginList = useInvalidateInstalledPluginList() const handleFetchNewVersion = async () => { try { const fetchedReleases = await fetchReleases(author, pluginName) - if (fetchedReleases.length === 0) - return - const versions = fetchedReleases.map(release => release.tag_name) - const latestVersion = getLatestVersion(versions) - if (compareVersion(latestVersion, meta!.version) === 1) { + if (checkForUpdates(fetchedReleases, meta!.version)) { setShowUpdatePluginModal({ onSaveCallback: () => { invalidateInstalledPluginList() @@ -87,11 +82,19 @@ const Action: FC = ({ }) } } - catch { - Toast.notify({ - type: 'error', - message: 'Failed to compare versions', - }) + catch (error) { + if (error instanceof Error) { + Toast.notify({ + type: 'error', + message: error.message, + }) + } + else { + Toast.notify({ + type: 'error', + message: 'Failed to compare versions', + }) + } } } @@ -108,6 +111,7 @@ const Action: FC = ({ hideDeleteConfirm() onDelete() } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [installationId, onDelete]) return (
diff --git a/web/app/components/plugins/plugin-item/index.tsx b/web/app/components/plugins/plugin-item/index.tsx index 4ac2c80d7d..eb833e0781 100644 --- a/web/app/components/plugins/plugin-item/index.tsx +++ b/web/app/components/plugins/plugin-item/index.tsx @@ -82,7 +82,7 @@ const PluginItem: FC = ({
{verified && <RiVerifiedBadgeLine className="shrink-0 ml-0.5 w-4 h-4 text-text-accent" />} - <Badge className='ml-1' text={plugin.version} /> + <Badge className='ml-1' text={source === PluginSource.github ? plugin.meta!.version : plugin.version} /> </div> <div className='flex items-center justify-between'> <Description text={description[locale]} descriptionLineRows={1}></Description>