mirror of
https://seed.radicle.dev/rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5.git
synced 2026-11-15 11:20:36 +08:00
Add infinite scrolling for patches listing
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
patchStatusColor,
|
||||
} from "@app/lib/utils";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { onMount } from "svelte";
|
||||
import { push } from "@app/lib/router";
|
||||
|
||||
import DiffStatBadge from "./DiffStatBadge.svelte";
|
||||
@@ -16,6 +17,16 @@
|
||||
import InlineTitle from "./InlineTitle.svelte";
|
||||
import NodeId from "./NodeId.svelte";
|
||||
|
||||
let stats: Stats | undefined = undefined;
|
||||
|
||||
onMount(async () => {
|
||||
stats = await invoke<Stats>("diff_stats", {
|
||||
rid,
|
||||
base: patch.base,
|
||||
head: patch.head,
|
||||
});
|
||||
});
|
||||
|
||||
export let patch: Patch;
|
||||
export let rid: string;
|
||||
</script>
|
||||
@@ -81,9 +92,9 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="global-flex">
|
||||
{#await invoke<Stats>( "diff_stats", { rid, base: patch.base, head: patch.head }, ) then stats}
|
||||
{#if stats}
|
||||
<DiffStatBadge {stats} />
|
||||
{/await}
|
||||
{/if}
|
||||
{#each patch.labels as label}
|
||||
<div class="global-counter txt-small">{label}</div>
|
||||
{/each}
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
}
|
||||
</style>
|
||||
|
||||
<Layout {repo} selfDid={`did:key:${config.publicKey}`}>
|
||||
<Layout>
|
||||
<svelte:fragment slot="breadcrumbs">
|
||||
<Link route={{ resource: "home" }}>
|
||||
<NodeId
|
||||
|
||||
@@ -100,9 +100,7 @@
|
||||
</div>
|
||||
|
||||
<div class="global-flex txt-small" style:margin="0.5rem 0">
|
||||
<Link
|
||||
variant="tab"
|
||||
route={{ resource: "repo.patches", rid: repo.rid, status: "all" }}>
|
||||
<Link variant="tab" route={{ resource: "repo.patches", rid: repo.rid }}>
|
||||
<div class="global-flex"><Icon name="patch" />Patches</div>
|
||||
<div class="global-counter">
|
||||
{project.meta.patches.draft +
|
||||
|
||||
@@ -1,9 +1,30 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
|
||||
import Header from "@app/components/Header.svelte";
|
||||
import Icon from "@app/components/Icon.svelte";
|
||||
import NakedButton from "@app/components/NakedButton.svelte";
|
||||
|
||||
export let loadMore: (() => Promise<void>) | undefined = undefined;
|
||||
|
||||
let hidden = false;
|
||||
let listElement: HTMLElement;
|
||||
let loading = false;
|
||||
|
||||
onMount(() => {
|
||||
if (listElement && loadMore) {
|
||||
listElement.addEventListener("scroll", async () => {
|
||||
if (
|
||||
listElement.scrollTop + listElement.clientHeight >=
|
||||
listElement.scrollHeight - 600 &&
|
||||
loading === false
|
||||
) {
|
||||
loading = true;
|
||||
void loadMore().finally(() => (loading = false));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@@ -64,7 +85,7 @@
|
||||
<slot name="sidebar" />
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<div class="content" bind:this={listElement}>
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
}
|
||||
</style>
|
||||
|
||||
<Layout {repo} selfDid={`did:key:${config.publicKey}`}>
|
||||
<Layout>
|
||||
<svelte:fragment slot="breadcrumbs">
|
||||
<Link route={{ resource: "home" }}>
|
||||
<NodeId
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
<script lang="ts">
|
||||
import type { Config } from "@bindings/Config";
|
||||
import type { PaginatedQuery } from "@bindings/PaginatedQuery";
|
||||
import type { Patch } from "@bindings/Patch";
|
||||
import type { PatchStatus } from "./router";
|
||||
import type { RepoInfo } from "@bindings/RepoInfo";
|
||||
|
||||
import Layout from "./Layout.svelte";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
|
||||
import Layout from "./Layout.svelte";
|
||||
import Border from "@app/components/Border.svelte";
|
||||
import CopyableId from "@app/components/CopyableId.svelte";
|
||||
import Icon from "@app/components/Icon.svelte";
|
||||
@@ -15,9 +17,28 @@
|
||||
import RepoHeader from "@app/components/RepoHeader.svelte";
|
||||
|
||||
export let repo: RepoInfo;
|
||||
export let patches: Patch[];
|
||||
export let patches: PaginatedQuery<Patch[]>;
|
||||
export let config: Config;
|
||||
export let status: PatchStatus;
|
||||
export let status: PatchStatus | undefined = undefined;
|
||||
|
||||
$: items = patches.content;
|
||||
$: more = patches.more;
|
||||
$: cursor = patches.cursor;
|
||||
|
||||
async function loadMore() {
|
||||
if (more) {
|
||||
const p = await invoke<PaginatedQuery<Patch[]>>("list_patches", {
|
||||
rid: repo.rid,
|
||||
skip: cursor + 20,
|
||||
status,
|
||||
take: 20,
|
||||
});
|
||||
|
||||
cursor = p.cursor;
|
||||
more = p.more;
|
||||
items = [...items, ...p.content];
|
||||
}
|
||||
}
|
||||
|
||||
$: project = repo.payloads["xyz.radicle.project"]!;
|
||||
</script>
|
||||
@@ -31,7 +52,7 @@
|
||||
}
|
||||
</style>
|
||||
|
||||
<Layout>
|
||||
<Layout {loadMore}>
|
||||
<svelte:fragment slot="breadcrumbs">
|
||||
<Link route={{ resource: "home" }}>
|
||||
<NodeId
|
||||
@@ -77,8 +98,8 @@
|
||||
</div>
|
||||
<div class="global-flex txt-small" style:margin="0.5rem 0">
|
||||
<Link
|
||||
variant={status === "all" ? "active" : "tab"}
|
||||
route={{ resource: "repo.patches", rid: repo.rid, status: "all" }}>
|
||||
variant={status === undefined ? "active" : "tab"}
|
||||
route={{ resource: "repo.patches", rid: repo.rid }}>
|
||||
<div class="global-flex"><Icon name="patch" />Patches</div>
|
||||
<div class="global-counter">
|
||||
{project.meta.patches.draft +
|
||||
@@ -133,13 +154,13 @@
|
||||
</svelte:fragment>
|
||||
|
||||
<div class="list">
|
||||
{#each patches as patch}
|
||||
{#each items as patch}
|
||||
<PatchTeaser rid={repo.rid} {patch} />
|
||||
{/each}
|
||||
|
||||
{#if patches.length === 0}
|
||||
{#if patches.content.length === 0}
|
||||
<div class="txt-missing txt-small">
|
||||
{#if status === "all"}
|
||||
{#if status === undefined}
|
||||
No patches.
|
||||
{:else}
|
||||
No {status} patches.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { Config } from "@bindings/Config";
|
||||
import type { PaginatedQuery } from "@bindings/PaginatedQuery";
|
||||
import type { Issue } from "@bindings/Issue";
|
||||
import type { Patch } from "@bindings/Patch";
|
||||
import type { RepoInfo } from "@bindings/RepoInfo";
|
||||
@@ -41,7 +42,7 @@ export interface LoadedRepoIssuesRoute {
|
||||
};
|
||||
}
|
||||
|
||||
export type PatchStatus = "all" | Patch["state"]["status"];
|
||||
export type PatchStatus = Patch["state"]["status"];
|
||||
|
||||
export interface RepoPatchRoute {
|
||||
resource: "repo.patch";
|
||||
@@ -63,7 +64,7 @@ export interface LoadedRepoPatchRoute {
|
||||
export interface RepoPatchesRoute {
|
||||
resource: "repo.patches";
|
||||
rid: string;
|
||||
status: PatchStatus;
|
||||
status?: PatchStatus;
|
||||
}
|
||||
|
||||
export interface LoadedRepoPatchesRoute {
|
||||
@@ -71,8 +72,8 @@ export interface LoadedRepoPatchesRoute {
|
||||
params: {
|
||||
repo: RepoInfo;
|
||||
config: Config;
|
||||
patches: Patch[];
|
||||
status: PatchStatus;
|
||||
patches: PaginatedQuery<Patch[]>;
|
||||
status?: PatchStatus;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -94,9 +95,8 @@ export async function loadPatch(
|
||||
rid: route.rid,
|
||||
});
|
||||
const config: Config = await invoke("config");
|
||||
const patches: Patch[] = await invoke("list_patches", {
|
||||
const patches: PaginatedQuery<Patch[]> = await invoke("list_patches", {
|
||||
rid: route.rid,
|
||||
status: "all",
|
||||
});
|
||||
const patch: Patch = await invoke("patch_by_id", {
|
||||
rid: route.rid,
|
||||
@@ -109,7 +109,7 @@ export async function loadPatch(
|
||||
|
||||
return {
|
||||
resource: "repo.patch",
|
||||
params: { repo, config, patch, patches, revisions },
|
||||
params: { repo, config, patch, patches: patches.content, revisions },
|
||||
};
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ export async function loadPatches(
|
||||
rid: route.rid,
|
||||
});
|
||||
const config: Config = await invoke("config");
|
||||
const patches: Patch[] = await invoke("list_patches", {
|
||||
const patches: PaginatedQuery<Patch[]> = await invoke("list_patches", {
|
||||
rid: route.rid,
|
||||
status: route.status,
|
||||
});
|
||||
@@ -243,7 +243,7 @@ export function repoUrlToRoute(
|
||||
) {
|
||||
return { resource: "repo.patches", rid, status };
|
||||
} else {
|
||||
return { resource: "repo.patches", rid, status: "all" };
|
||||
return { resource: "repo.patches", rid };
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user