diff --git a/src/components/repo/RepoCloneUrl.tsx b/src/components/repo/RepoCloneUrl.tsx new file mode 100644 index 0000000..da9d751 --- /dev/null +++ b/src/components/repo/RepoCloneUrl.tsx @@ -0,0 +1,55 @@ +import type { Handle } from '@atcute/lexicons' +import { useEffect, useState } from 'react' +import { getRepoName, type Repo } from '../../lib/tangled' + +type RepoCloneUrlProps = { + handle: Handle + repo: Repo +} + +export function RepoCloneUrl({ handle, repo }: RepoCloneUrlProps) { + const [status, setStatus] = useState<'idle' | 'copied' | 'failed'>('idle') + const cloneUrl = buildCloneUri(handle, repo) + + async function copyCloneUrl() { + try { + await navigator.clipboard.writeText(cloneUrl) + setStatus('copied') + } catch { + setStatus('failed') + } + } + + useEffect(() => { + if (status !== 'copied') return + + const timeoutId = window.setTimeout(() => { + setStatus('idle') + }, 2000) + + return () => { + window.clearTimeout(timeoutId) + } + }, [status]) + + return ( +
+ Clone + + {cloneUrl} + + +
+ ) +} + +function buildCloneUri(handle: Handle, repo: Repo) { + const name = getRepoName(repo) + return `git@tangled.org:${handle}/${name}.git` +} diff --git a/src/components/repo/RepoView.tsx b/src/components/repo/RepoView.tsx index 0ec1ff2..fc35509 100644 --- a/src/components/repo/RepoView.tsx +++ b/src/components/repo/RepoView.tsx @@ -1,16 +1,19 @@ +import type { Handle } from '@atcute/lexicons' import Markdown from 'react-markdown' import rehypeRaw from 'rehype-raw' import rehypeSanitize from 'rehype-sanitize' -import type { Repo } from '../../lib/tangled/index' +import type { Repo } from '../../lib/tangled' import { getRepoName } from '../../lib/tangled/repo' import { SurfaceCard } from '../shared/SurfaceCard' +import { RepoCloneUrl } from './RepoCloneUrl' import { RepoStarCount } from './RepoStarCount' type RepoProps = { + handle: Handle repo: Repo } -export function RepoView({ repo }: RepoProps) { +export function RepoView({ handle, repo }: RepoProps) { const { value } = repo const name = getRepoName(repo) const repoDid = value.repoDid @@ -49,6 +52,8 @@ export function RepoView({ repo }: RepoProps) { )} + + ) } diff --git a/src/pages/RepoPage.tsx b/src/pages/RepoPage.tsx index cc615f5..f375734 100644 --- a/src/pages/RepoPage.tsx +++ b/src/pages/RepoPage.tsx @@ -5,14 +5,14 @@ import type { $output as MiniDoc } from '@atcute/microcosm/types/blue/microcosm/ import type { $output as RepoTreeResponse } from '@atcute/tangled/types/repo/tree' import { useEffect, useState } from 'react' import { useParams, useSearchParams } from 'react-router-dom' -import { RepoPageSkeleton } from '../components/shared/PageSkeletons' import { PageContainer } from '../components/layout/PageContainer' import { ProfileByline } from '../components/profile/ProfileByline' import { RepoReadme } from '../components/repo/RepoReadme' -import { RepoTabs } from '../components/repo/RepoTabs' import { parseRepoSection } from '../components/repo/repoSections' +import { RepoTabs } from '../components/repo/RepoTabs' import { RepoView } from '../components/repo/RepoView' import { RepoWorkspace } from '../components/repo/RepoWorkspace' +import { RepoPageSkeleton } from '../components/shared/PageSkeletons' import { SurfaceCard } from '../components/shared/SurfaceCard' import { getProfile as getBskyProfile } from '../lib/bsky/actor' import { getMiniDoc } from '../lib/microcosm' @@ -106,7 +106,7 @@ export function RepoPage() { />
- +