Radish alpha
r
rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5
Radicle web interface
Radicle
Git
Show a confirmation dialog when stopping project seeding
Merged rudolfs opened 2 years ago
4 files changed +68 -89 d216caec 2d57aaaf
modified src/components/Popover.svelte
@@ -62,7 +62,7 @@
      style:top={popoverPositionTop}
      style:padding={popoverPadding}
      style:border-radius={popoverBorderRadius}>
-
      <slot name="popover" />
+
      <slot name="popover" {toggle} />
    </div>
  {/if}
</div>
modified src/views/projects/Header/SeedButton.svelte
@@ -1,15 +1,59 @@
<script lang="ts">
+
  import * as modal from "@app/lib/modal";
+
  import { httpdStore, api } from "@app/lib/httpd";
+

  import Button from "@app/components/Button.svelte";
-
  import Command from "@app/components/Command.svelte";
-
  import ExternalLink from "@app/components/ExternalLink.svelte";
+
  import ErrorModal from "@app/modals/ErrorModal.svelte";
  import IconSmall from "@app/components/IconSmall.svelte";
  import Popover from "@app/components/Popover.svelte";

-
  export let disabled: boolean;
  export let projectId: string;
  export let seedCount: number;
  export let seeding: boolean;
-
  export let editSeeding: (() => Promise<void>) | undefined;
+

+
  let editSeedingInProgress = false;
+

+
  async function editSeeding() {
+
    if ($httpdStore.state === "authenticated") {
+
      try {
+
        editSeedingInProgress = true;
+
        if (seeding) {
+
          await api.stopSeedingById(projectId, $httpdStore.session.id);
+
        } else {
+
          await api.seedById(projectId, $httpdStore.session.id);
+
        }
+
        seeding = !seeding;
+
      } catch (error) {
+
        if (error instanceof Error) {
+
          modal.show({
+
            component: ErrorModal,
+
            props: {
+
              title: seeding
+
                ? "Stop seeding project failed"
+
                : "Seeding project failed",
+
              subtitle: [
+
                `There was an error while trying to ${
+
                  seeding ? "stop seeding" : "seed"
+
                } this project.`,
+
                "Check your radicle-httpd logs for details.",
+
              ],
+
              error: {
+
                message: error.message,
+
                stack: error.stack,
+
              },
+
            },
+
          });
+
        }
+
      } finally {
+
        editSeedingInProgress = false;
+
      }
+
    }
+
  }
+

+
  $: canEditSeeding =
+
    !editSeedingInProgress &&
+
    $httpdStore.state === "authenticated" &&
+
    $httpdStore.node.state === "running";
</script>

<style>
@@ -19,13 +63,6 @@
    font-weight: var(--font-weight-regular);
    margin-bottom: 0.75rem;
  }
-
  code {
-
    font-family: var(--font-family-monospace);
-
    font-size: var(--font-size-small);
-
    background-color: var(--color-fill-ghost);
-
    border-radius: var(--border-radius-tiny);
-
    padding: 0.125rem 0.25rem;
-
  }
  .title-counter {
    display: flex;
    gap: 0.5rem;
@@ -50,11 +87,11 @@

<Popover popoverPositionTop="2.5rem" popoverPositionRight="0">
  <Button
-
    {disabled}
+
    disabled={!canEditSeeding}
    slot="toggle"
    let:toggle
    on:click={async () => {
-
      if (editSeeding) {
+
      if (!seeding && canEditSeeding) {
        await editSeeding();
      } else {
        toggle();
@@ -67,36 +104,29 @@
      <span
        class="counter"
        class:seeding
-
        class:disabled
+
        class:disabled={!canEditSeeding}
        style:font-weight="var(--font-weight-regular)">
        {seedCount}
      </span>
    </span>
  </Button>

-
  <div slot="popover" style:width={seeding ? "19.5rem" : "30.5rem"}>
+
  <div slot="popover" let:toggle style:width={seeding ? "19.5rem" : "30.5rem"}>
+
    <div class="seed-label txt-bold">Stop seeding</div>
    <div class="seed-label">
-
      Use the <ExternalLink href="https://radicle.xyz/#try">
-
        Radicle CLI
-
      </ExternalLink>
-
      to {seeding ? "stop seeding" : "seed"} this project.
-
      {#if !seeding}
-
        <br />
-
        <br />
-
        The
-
        <code>seed</code>
-
        command serves a dual purpose:
-
        <ul style:padding="0 1rem" style:margin-top="0.5rem">
-
          <li>
-
            Keeps your local Radicle node in sync with updates from this
-
            project.
-
          </li>
-
          <li>
-
            Propagates them across the Radicle network to other peers like you.
-
          </li>
-
        </ul>
-
      {/if}
+
      Are you sure you want to stop seeding this project? If you don't seed a
+
      project it won't appear in the local projects section anymore and any
+
      changes you make to it won't propagate to the network.
    </div>
-
    <Command command={`rad seed ${projectId} ${seeding ? "--delete" : ""}`} />
+
    <Button
+
      styleWidth="100%"
+
      disabled={editSeedingInProgress}
+
      on:click={async () => {
+
        await editSeeding();
+
        toggle();
+
      }}>
+
      <IconSmall name="network" />
+
      Stop seeding
+
    </Button>
  </div>
</Popover>
modified src/views/projects/Source/ProjectNameHeader.svelte
@@ -1,14 +1,11 @@
<script lang="ts">
  import type { BaseUrl, Project } from "@httpd-client";

-
  import * as modal from "@app/lib/modal";
-
  import { httpdStore, api } from "@app/lib/httpd";
  import { twemoji } from "@app/lib/utils";

  import Badge from "@app/components/Badge.svelte";
  import CloneButton from "../Header/CloneButton.svelte";
  import CopyableId from "@app/components/CopyableId.svelte";
-
  import ErrorModal from "@app/modals/ErrorModal.svelte";
  import InlineMarkdown from "@app/components/InlineMarkdown.svelte";
  import Link from "@app/components/Link.svelte";
  import IconSmall from "@app/components/IconSmall.svelte";
@@ -20,53 +17,6 @@
  export let seeding: boolean;
  export let preferredSeeds: string[];
  export let publicExplorer: string;
-

-
  $: canEditSeeding =
-
    session &&
-
    $httpdStore.state === "authenticated" &&
-
    $httpdStore.node.state === "running";
-

-
  let editSeedingInProgress = false;
-

-
  async function editSeeding() {
-
    if ($httpdStore.state === "authenticated") {
-
      try {
-
        editSeedingInProgress = true;
-
        if (seeding) {
-
          await api.stopSeedingById(project.id, $httpdStore.session.id);
-
        } else {
-
          await api.seedById(project.id, $httpdStore.session.id);
-
        }
-
        seeding = !seeding;
-
      } catch (error) {
-
        if (error instanceof Error) {
-
          modal.show({
-
            component: ErrorModal,
-
            props: {
-
              title: seeding
-
                ? "Stop seeding project failed"
-
                : "Seeding project failed",
-
              subtitle: [
-
                `There was an error while trying to ${
-
                  seeding ? "stop seeding" : "seed"
-
                } this project.`,
-
                "Check your radicle-httpd logs for details.",
-
              ],
-
              error: {
-
                message: error.message,
-
                stack: error.stack,
-
              },
-
            },
-
          });
-
        }
-
      } finally {
-
        editSeedingInProgress = false;
-
      }
-
    }
-
  }
-

-
  $: session =
-
    $httpdStore.state === "authenticated" ? $httpdStore.session : undefined;
</script>

<style>
@@ -131,8 +81,6 @@
      <CloneButton {baseUrl} id={project.id} name={project.name} />
      <SeedButton
        {seeding}
-
        disabled={editSeedingInProgress}
-
        editSeeding={canEditSeeding ? editSeeding : undefined}
        seedCount={project.seeding}
        projectId={project.id} />
    </div>
modified tests/e2e/node.spec.ts
@@ -46,6 +46,7 @@ test("seeding projects", async ({ page, authenticatedPeer }) => {

  await page.goto(authenticatedPeer.ridUrl(rid));
  await page.getByRole("button", { name: "Seeding" }).click();
+
  await page.getByRole("button", { name: "Stop seeding" }).click();
  await expect(page.getByRole("button", { name: "Seed 1" })).toBeVisible();

  await page.getByRole("button", { name: "Seed 1" }).click();