From 7def19397cfab63c4becb158669d7a7571c77428 Mon Sep 17 00:00:00 2001 From: AkaraChen Date: Mon, 15 Jun 2026 10:14:44 +0800 Subject: [PATCH 1/4] KIT-48: copy skills.sh search result links --- crates/desktop/src/lib/locales/en.ts | 4 + crates/desktop/src/lib/locales/zh-Hans.ts | 4 + crates/desktop/src/lib/locales/zh-Hant.ts | 4 + crates/desktop/src/pages/skills-sh/search.tsx | 130 +++++++++++++----- 4 files changed, 109 insertions(+), 33 deletions(-) diff --git a/crates/desktop/src/lib/locales/en.ts b/crates/desktop/src/lib/locales/en.ts index cd5bb06f..2b05bac2 100644 --- a/crates/desktop/src/lib/locales/en.ts +++ b/crates/desktop/src/lib/locales/en.ts @@ -772,6 +772,10 @@ export default { searchToFindSkills: "Search to find skills from skills.sh", poweredByVercel: "Powered by Vercel", dataFromSkillsSh: "Data from skills.sh", + copySkillsShLink: "Copy skills.sh link", + copySkillsShLinkHint: "Click to copy this skills.sh URL.", + skillsShLinkCopied: "skills.sh link copied", + skillsShLinkCopyFailed: "Failed to copy skills.sh link", // MCP Detail connection: "Connection", diff --git a/crates/desktop/src/lib/locales/zh-Hans.ts b/crates/desktop/src/lib/locales/zh-Hans.ts index 3adfa9a8..60ff728c 100644 --- a/crates/desktop/src/lib/locales/zh-Hans.ts +++ b/crates/desktop/src/lib/locales/zh-Hans.ts @@ -763,6 +763,10 @@ export default { searchToFindSkills: "搜索以从 skills.sh 查找技能", poweredByVercel: "由 Vercel 提供支持", dataFromSkillsSh: "数据来自 skills.sh", + copySkillsShLink: "复制 skills.sh 链接", + copySkillsShLinkHint: "点击可复制这个 skills.sh 地址。", + skillsShLinkCopied: "skills.sh 链接已复制", + skillsShLinkCopyFailed: "复制 skills.sh 链接失败", // Projects addProject: "添加项目", diff --git a/crates/desktop/src/lib/locales/zh-Hant.ts b/crates/desktop/src/lib/locales/zh-Hant.ts index 2b775d77..cb476c1b 100644 --- a/crates/desktop/src/lib/locales/zh-Hant.ts +++ b/crates/desktop/src/lib/locales/zh-Hant.ts @@ -761,6 +761,10 @@ export default { searchToFindSkills: "搜尋以從 skills.sh 尋找技能", poweredByVercel: "由 Vercel 提供支援", dataFromSkillsSh: "資料來自 skills.sh", + copySkillsShLink: "複製 skills.sh 連結", + copySkillsShLinkHint: "點擊可複製這個 skills.sh 地址。", + skillsShLinkCopied: "skills.sh 連結已複製", + skillsShLinkCopyFailed: "複製 skills.sh 連結失敗", // Projects addProject: "新增專案", diff --git a/crates/desktop/src/pages/skills-sh/search.tsx b/crates/desktop/src/pages/skills-sh/search.tsx index 63f6d088..b90d812d 100644 --- a/crates/desktop/src/pages/skills-sh/search.tsx +++ b/crates/desktop/src/pages/skills-sh/search.tsx @@ -1,6 +1,7 @@ import { MagnifyingGlassIcon } from "@heroicons/react/24/solid"; -import { Button, Spinner } from "@heroui/react"; +import { Button, Spinner, Tooltip, toast } from "@heroui/react"; import { useInfiniteQuery } from "@tanstack/react-query"; +import { writeText } from "@tauri-apps/plugin-clipboard-manager"; import { useQueryState } from "nuqs"; import { useCallback, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; @@ -23,6 +24,7 @@ import { useSkillInstall } from "./hooks/use-skill-install"; const BATCH_SIZE = 20; const FETCH_SIZE = 100; const ROW_HEIGHT = 48; +const SKILLS_SH_BASE_URL = "https://www.skills.sh"; const tableComponents: TableComponents = { Table: ({ style, ...props }) => ( @@ -45,6 +47,18 @@ const tableComponents: TableComponents = { ), }; +function buildSkillsShUrl(skill: MarketSkill) { + const sourceParts = skill.source.split("/").filter(Boolean); + const pathParts = + sourceParts[0] === "github" ? sourceParts.slice(1) : sourceParts; + const skillSegment = skill.slug || skill.name; + const urlSegments = [...pathParts, skillSegment] + .filter(Boolean) + .map((part) => encodeURIComponent(part)); + + return `${SKILLS_SH_BASE_URL}/${urlSegments.join("/")}`; +} + export default function SkillsSearchPage() { const { t, i18n } = useTranslation(); const api = useApi(); @@ -103,6 +117,25 @@ export default function SkillsSearchPage() { const hasMore = visibleCount < searchResults.length; + const handleCopySkillsShUrl = useCallback( + async (skill: MarketSkill) => { + const skillsShUrl = buildSkillsShUrl(skill); + + try { + await writeText(skillsShUrl); + toast.success(t("skillsShLinkCopied")); + } catch (error) { + console.error("Failed to copy skills.sh URL:", error); + toast.danger( + error instanceof Error + ? error.message + : t("skillsShLinkCopyFailed"), + ); + } + }, + [t], + ); + const handleEndReached = useCallback(() => { if (hasMore && !isFetching) { setVisibleCount((c) => @@ -170,38 +203,69 @@ export default function SkillsSearchPage() { fixedItemHeight={ROW_HEIGHT} style={{ height: "100%" }} components={tableComponents} - itemContent={(_index, skill) => ( - <> - - - {skill.name} - - - - - {compactFormatter.format( - skill.installs, - )} - - - - - {skill.source} - - - - - - - )} + itemContent={(_index, skill) => { + const skillsShUrl = buildSkillsShUrl(skill); + + return ( + <> + + + {skill.name} + + + + + {compactFormatter.format( + skill.installs, + )} + + + + + + + + +
+
+ {skillsShUrl} +
+
+ {t( + "copySkillsShLinkHint", + )} +
+
+
+
+ + + + + + ); + }} > From 285cbcabca3a8740bdfe7c6803df155709a65db3 Mon Sep 17 00:00:00 2001 From: AkaraChen Date: Mon, 15 Jun 2026 10:28:31 +0800 Subject: [PATCH 2/4] KIT-48: address skills.sh link review --- crates/desktop/src/pages/skills-sh/search.tsx | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/crates/desktop/src/pages/skills-sh/search.tsx b/crates/desktop/src/pages/skills-sh/search.tsx index b90d812d..e82869fb 100644 --- a/crates/desktop/src/pages/skills-sh/search.tsx +++ b/crates/desktop/src/pages/skills-sh/search.tsx @@ -49,8 +49,21 @@ const tableComponents: TableComponents = { function buildSkillsShUrl(skill: MarketSkill) { const sourceParts = skill.source.split("/").filter(Boolean); - const pathParts = - sourceParts[0] === "github" ? sourceParts.slice(1) : sourceParts; + const pathParts = (() => { + if (sourceParts.length === 0) { + return []; + } + + if (sourceParts[0] === "github") { + return sourceParts.slice(1); + } + + if (sourceParts[0] === "site") { + return sourceParts; + } + + return ["site", ...sourceParts]; + })(); const skillSegment = skill.slug || skill.name; const urlSegments = [...pathParts, skillSegment] .filter(Boolean) @@ -126,11 +139,7 @@ export default function SkillsSearchPage() { toast.success(t("skillsShLinkCopied")); } catch (error) { console.error("Failed to copy skills.sh URL:", error); - toast.danger( - error instanceof Error - ? error.message - : t("skillsShLinkCopyFailed"), - ); + toast.danger(t("skillsShLinkCopyFailed")); } }, [t], From 192d8b80aa10a15b009db075dd8a2256c5280e69 Mon Sep 17 00:00:00 2001 From: AkaraChen Date: Mon, 15 Jun 2026 11:10:19 +0800 Subject: [PATCH 3/4] KIT-48: remove skills link tooltip --- crates/desktop/src/lib/locales/en.ts | 1 - crates/desktop/src/lib/locales/zh-Hans.ts | 1 - crates/desktop/src/lib/locales/zh-Hant.ts | 1 - crates/desktop/src/pages/skills-sh/search.tsx | 46 ++++++------------- 4 files changed, 13 insertions(+), 36 deletions(-) diff --git a/crates/desktop/src/lib/locales/en.ts b/crates/desktop/src/lib/locales/en.ts index 2b05bac2..77c6205d 100644 --- a/crates/desktop/src/lib/locales/en.ts +++ b/crates/desktop/src/lib/locales/en.ts @@ -773,7 +773,6 @@ export default { poweredByVercel: "Powered by Vercel", dataFromSkillsSh: "Data from skills.sh", copySkillsShLink: "Copy skills.sh link", - copySkillsShLinkHint: "Click to copy this skills.sh URL.", skillsShLinkCopied: "skills.sh link copied", skillsShLinkCopyFailed: "Failed to copy skills.sh link", diff --git a/crates/desktop/src/lib/locales/zh-Hans.ts b/crates/desktop/src/lib/locales/zh-Hans.ts index 60ff728c..aa6dbd9c 100644 --- a/crates/desktop/src/lib/locales/zh-Hans.ts +++ b/crates/desktop/src/lib/locales/zh-Hans.ts @@ -764,7 +764,6 @@ export default { poweredByVercel: "由 Vercel 提供支持", dataFromSkillsSh: "数据来自 skills.sh", copySkillsShLink: "复制 skills.sh 链接", - copySkillsShLinkHint: "点击可复制这个 skills.sh 地址。", skillsShLinkCopied: "skills.sh 链接已复制", skillsShLinkCopyFailed: "复制 skills.sh 链接失败", diff --git a/crates/desktop/src/lib/locales/zh-Hant.ts b/crates/desktop/src/lib/locales/zh-Hant.ts index cb476c1b..36bd1cee 100644 --- a/crates/desktop/src/lib/locales/zh-Hant.ts +++ b/crates/desktop/src/lib/locales/zh-Hant.ts @@ -762,7 +762,6 @@ export default { poweredByVercel: "由 Vercel 提供支援", dataFromSkillsSh: "資料來自 skills.sh", copySkillsShLink: "複製 skills.sh 連結", - copySkillsShLinkHint: "點擊可複製這個 skills.sh 地址。", skillsShLinkCopied: "skills.sh 連結已複製", skillsShLinkCopyFailed: "複製 skills.sh 連結失敗", diff --git a/crates/desktop/src/pages/skills-sh/search.tsx b/crates/desktop/src/pages/skills-sh/search.tsx index e82869fb..38e7cb2f 100644 --- a/crates/desktop/src/pages/skills-sh/search.tsx +++ b/crates/desktop/src/pages/skills-sh/search.tsx @@ -1,5 +1,5 @@ import { MagnifyingGlassIcon } from "@heroicons/react/24/solid"; -import { Button, Spinner, Tooltip, toast } from "@heroui/react"; +import { Button, Spinner, toast } from "@heroui/react"; import { useInfiniteQuery } from "@tanstack/react-query"; import { writeText } from "@tauri-apps/plugin-clipboard-manager"; import { useQueryState } from "nuqs"; @@ -213,8 +213,6 @@ export default function SkillsSearchPage() { style={{ height: "100%" }} components={tableComponents} itemContent={(_index, skill) => { - const skillsShUrl = buildSkillsShUrl(skill); - return ( <> @@ -230,36 +228,18 @@ export default function SkillsSearchPage() { - - - - - -
-
- {skillsShUrl} -
-
- {t( - "copySkillsShLinkHint", - )} -
-
-
-
+