Radish alpha
r
Radicle web interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
Show fetch more button only when more projects are available
Sebastian Martinez committed 3 years ago
commit 698f222d61f84b2bda862f4201f5564e1fa107b5
parent 9cb3928481f7579b88b7aba629e62b602fdd12ba
6 files changed +70 -16
modified src/Async.svelte
@@ -1,7 +1,9 @@
<script lang="ts">
  import Loading from "@app/Loading.svelte";

-
  export let fetch: any;
+
  type T = $$Generic;
+

+
  export let fetch: Promise<T>;
</script>

{#await fetch}
modified src/List.svelte
@@ -5,13 +5,12 @@

  type Item = $$Generic;

+
  export let complete = false;
  export let items: Item[];
  export let query: () => Promise<Item[]>;

  // Used to handle the display of the trigger to load more items, according to the current loading state.
  let loading = false;
-
  // Should be changed to true, once no more items are being returned.
-
  let complete = false;

  const transitionParams = { duration: 200 };

modified src/Profile.svelte
@@ -1,6 +1,8 @@
<script lang="ts">
  import type { SvelteComponent } from "svelte";
  import type { Config } from "@app/config";
+
  import type { Seed, Stats } from "@app/base/seeds/Seed";
+
  import type { ProjectInfo } from "@app/project";
  import Address from "@app/Address.svelte";
  import Avatar from "@app/Avatar.svelte";
  import Icon from "@app/Icon.svelte";
@@ -39,6 +41,18 @@
    transferOwnerForm = TransferOwnership;
  };

+
  const getProjectsAndStats = async (
+
    seed: Seed,
+
    id?: string,
+
  ): Promise<{
+
    stats: Stats;
+
    projects: ProjectInfo[];
+
  }> => {
+
    const stats = await seed.getStats();
+
    const projects = await seed.getProjects(10, id);
+
    return { stats, projects };
+
  };
+

  $: account = $session && $session.address;
  $: isOwner = (org: Org): boolean =>
    $session ? utils.isAddressEqual(org.owner, $session.address) : false;
@@ -447,8 +461,12 @@
      {/await}
    {/if}
    {#if profile.seed?.valid}
-
      <Async fetch={profile.seed.getProjects(10, profile.id)} let:result>
-
        <Projects {profile} seed={profile.seed} projects={result} />
+
      <Async fetch={getProjectsAndStats(profile.seed, profile.id)} let:result>
+
        <Projects
+
          {profile}
+
          seed={profile.seed}
+
          stats={result.stats}
+
          projects={result.projects} />
      </Async>
    {/if}
  </main>
modified src/base/seeds/Seed.ts
@@ -4,6 +4,11 @@ import * as proj from "@app/project";
import { isDomain, isLocal } from "@app/utils";
import { assert } from "@app/error";

+
export interface Stats {
+
  projects: { count: number };
+
  users: { count: number };
+
}
+

export class InvalidSeed {
  valid = false as const;

@@ -116,6 +121,13 @@ export class Seed {
    }));
  }

+
  async getStats(): Promise<{
+
    projects: { count: number };
+
    users: { count: number };
+
  }> {
+
    return new Request("/stats", this.api).get();
+
  }
+

  static async getPeer(host: Host): Promise<{ id: string }> {
    return new Request("/peer", host).get();
  }
modified src/base/seeds/View.svelte
@@ -1,5 +1,7 @@
<script lang="ts">
  import type { Config } from "@app/config";
+
  import type { Stats } from "@app/base/seeds/Seed";
+
  import type { ProjectInfo } from "@app/project";
  import { formatSeedId, formatSeedHost } from "@app/utils";
  import { Seed } from "@app/base/seeds/Seed";
  import Loading from "@app/Loading.svelte";
@@ -23,6 +25,17 @@
  const seedHost: Host = { host, port: null };
  let siweSession: SeedSession | null = null;

+
  const getProjectsAndStats = async (
+
    seed: Seed,
+
  ): Promise<{
+
    stats: Stats;
+
    projects: ProjectInfo[];
+
  }> => {
+
    const stats = await seed.getStats();
+
    const projects = await Project.getProjects(seedHost, { perPage: 10 });
+
    return { stats, projects };
+
  };
+

  $: if (session?.siwe) {
    const entries = Object.entries(session.siwe);
    const result = entries.find(([, session]) => session.domain === host);
@@ -164,8 +177,8 @@
      <div class="desktop" />
    </div>
    <!-- Seed Projects -->
-
    <Async fetch={Project.getProjects(seedHost, { perPage: 10 })} let:result>
-
      <Projects {seed} projects={result} />
+
    <Async fetch={getProjectsAndStats(seed)} let:result>
+
      <Projects {seed} projects={result.projects} stats={result.stats} />
    </Async>
  </main>
{:catch}
modified src/base/seeds/View/Projects.svelte
@@ -4,26 +4,33 @@
  import Widget from "@app/base/projects/Widget.svelte";
  import type { Profile } from "@app/profile";
  import type { ProjectInfo } from "@app/project";
-
  import type { Seed } from "@app/base/seeds/Seed";
+
  import type { Seed, Stats } from "@app/base/seeds/Seed";
  import List from "@app/List.svelte";

  export let seed: Seed;
  export let profile: Profile | null = null;
  export let projects: proj.ProjectInfo[];
+
  export let stats: Stats;

  // A pointer to the current page of projects added to the listing
  let page = 0;

  const fetchMoreProjects = async (): Promise<proj.ProjectInfo[]> => {
-
    const projects = await proj.Project.getProjects(seed.api, {
-
      perPage: 10,
-
      page: (page += 1),
-
    });
-
    if (projects.length > 0) {
-
      return projects;
+
    try {
+
      stats = await seed.getStats();
+
      const projects = await proj.Project.getProjects(seed.api, {
+
        perPage: 10,
+
        page: (page += 1),
+
      });
+
      if (projects.length > 0) {
+
        return projects;
+
      }
+
    } catch (e) {
+
      console.error(e);
    }

-
    // We return an empty array, for when no more projects are found, since List is looking for an iterable.
+
    // We return an empty array, for when no more projects are found, or an error is thrown
+
    // since List is looking for an iterable.
    return [];
  };

@@ -49,7 +56,10 @@
</style>

<div class="projects">
-
  <List items={projects} query={fetchMoreProjects}>
+
  <List
+
    bind:items={projects}
+
    complete={projects.length === stats.projects.count}
+
    query={fetchMoreProjects}>
    <svelte:fragment slot="list" let:items>
      {#each items as project}
        {#if project.head}