diff --git a/src/lib/archive.ts b/src/lib/archive.ts new file mode 100644 index 000000000..83e810089 --- /dev/null +++ b/src/lib/archive.ts @@ -0,0 +1,15 @@ +export const archiveUnsupportedMessage = + "The radicle-httpd on this node doesn't support archive downloads."; + +const supportedUrls = new Set(); + +export async function archiveDownloadSupported(url: string): Promise { + if (supportedUrls.has(url)) { + return true; + } + const response = await fetch(url, { method: "HEAD" }); + if (response.ok) { + supportedUrls.add(url); + } + return response.ok; +} diff --git a/src/views/repos/Commit.svelte b/src/views/repos/Commit.svelte index 950f7baaf..f836b6ad2 100644 --- a/src/views/repos/Commit.svelte +++ b/src/views/repos/Commit.svelte @@ -1,6 +1,10 @@ @@ -59,6 +68,10 @@ display: flex; gap: 0.5rem; } + .download-error { + font: var(--txt-body-m-regular); + width: 18rem; + } @@ -108,14 +121,30 @@ - {#if enabledArchiveDownload} - - - - {/if} + + +
+ {archiveUnsupportedMessage} +
+
diff --git a/src/views/repos/Header/CloneButton.svelte b/src/views/repos/Header/CloneButton.svelte index d8926491a..97a3cee82 100644 --- a/src/views/repos/Header/CloneButton.svelte +++ b/src/views/repos/Header/CloneButton.svelte @@ -2,12 +2,17 @@ import type { BaseUrl } from "@http-client"; import config from "@app/lib/config"; + import { + archiveDownloadSupported, + archiveUnsupportedMessage, + } from "@app/lib/archive"; import { parseRepositoryId } from "@app/lib/utils"; import Button from "@app/components/Button.svelte"; import Command from "@app/components/Command.svelte"; import ExternalLink from "@app/components/ExternalLink.svelte"; import Icon from "@app/components/Icon.svelte"; + import Loading from "@app/components/Loading.svelte"; import Popover from "@app/components/Popover.svelte"; import Radio from "@app/components/Radio.svelte"; @@ -18,18 +23,15 @@ export let name: string; export let currentRefname: string; - let enabledArchiveDownload = false; - - void fetch( - `${baseUrlToString(baseUrl)}/raw/${id}/archive/${currentRefname}`, - { - method: "HEAD", - }, - ).then(response => { - enabledArchiveDownload = response.ok; - }); - let activeTab: "radicle" | "git" | "archive" = "radicle"; + let archiveProbe: Promise | undefined; + + function showArchiveTab() { + activeTab = "archive"; + archiveProbe = archiveDownloadSupported( + `${baseUrlToString(baseUrl)}/raw/${id}/archive/${currentRefname}`, + ); + } $: radCloneUrl = `rad clone ${id}`; $: portFragment = @@ -83,19 +85,15 @@ Git - {#if enabledArchiveDownload} -
- - {/if} +
+ @@ -119,17 +117,28 @@ {:else if activeTab === "archive"} -
- - -
- Note that a compressed archive of the source code does not include any - of the social artifacts such as issues or patches nor the git history. -
-
+ {#await archiveProbe} + + {:then supported} + {#if supported} +
+ + +
+ Note that a compressed archive of the source code does not include + any of the social artifacts such as issues or patches nor the git + history. +
+
+ {:else} + {archiveUnsupportedMessage} + {/if} + {:catch} + {archiveUnsupportedMessage} + {/await} {/if}