Skip to content

Commit 922ba21

Browse files
committed
feat(app): switch releases to R2-backed paginated feed
1 parent 84fd9ed commit 922ba21

8 files changed

Lines changed: 321 additions & 217 deletions

File tree

packages/app/app/app.vue

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ useHead({
1111
1212
useSeoMeta({
1313
title: "pkg.pr.new",
14-
description:
15-
"Search repositories on GitHub to list their continuous releases.",
14+
description: "Search repositories to list their continuous releases.",
1615
});
1716
</script>
1817

packages/app/app/components/Commits.vue

Lines changed: 76 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -113,58 +113,77 @@ onBeforeUnmount(() => {
113113
114114
// Pagination
115115
const fetching = ref(false);
116-
const fetchMoreForceDisabled = ref(!commitsWithRelease.value.length);
116+
const currentPage = ref(branch.target.history.pageInfo.currentPage || 1);
117+
const totalPages = computed(() => branch.target.history.pageInfo.totalPages || 1);
118+
const hasNextPage = computed(() => currentPage.value < totalPages.value);
119+
const hasPrevPage = computed(() => currentPage.value > 1);
117120
118-
async function fetchMore() {
119-
if (!branch.target.history.pageInfo.hasNextPage) {
120-
return;
121+
const paginationItems = computed<(number | "...")[]>(() => {
122+
const total = totalPages.value;
123+
const page = currentPage.value;
124+
if (total <= 7) {
125+
return Array.from({ length: total }, (_, i) => i + 1);
121126
}
122127
128+
const items: (number | "...")[] = [1];
129+
const start = Math.max(2, page - 1);
130+
const end = Math.min(total - 1, page + 1);
131+
132+
if (start > 2) {
133+
items.push("...");
134+
}
135+
for (let i = start; i <= end; i++) {
136+
items.push(i);
137+
}
138+
if (end < total - 1) {
139+
items.push("...");
140+
}
141+
items.push(total);
142+
return items;
143+
});
144+
145+
async function fetchPage(page: number) {
123146
if (fetching.value) {
124147
return;
125148
}
126149
127150
try {
128151
fetching.value = true;
129-
130-
const cursor = branch.target.history.pageInfo.endCursor;
131-
132152
const result = await $fetch("/api/repo/commits", {
133153
query: {
134154
owner: props.owner,
135155
repo: props.repo,
136-
cursor,
156+
page: String(page),
137157
},
138158
});
139159
140-
const count = commitsWithRelease.value.length;
141-
142-
branch.target = {
143-
...branch.target,
144-
history: {
145-
...branch.target.history,
146-
nodes: [...branch.target.history.nodes, ...result.target.history.nodes],
147-
pageInfo: result.target.history.pageInfo,
148-
},
149-
};
150-
151-
if (count === commitsWithRelease.value.length) {
152-
fetchMoreForceDisabled.value = true;
153-
}
160+
currentPage.value = result.target.history.pageInfo.currentPage || page;
161+
branch.id = result.id;
162+
branch.name = result.name;
163+
branch.target = result.target;
154164
} finally {
155165
fetching.value = false;
156166
}
157167
}
168+
169+
async function goNextPage() {
170+
if (!hasNextPage.value) {
171+
return;
172+
}
173+
await fetchPage(currentPage.value + 1);
174+
}
175+
176+
async function goPrevPage() {
177+
if (!hasPrevPage.value) {
178+
return;
179+
}
180+
await fetchPage(currentPage.value - 1);
181+
}
182+
158183
</script>
159184

160185
<template>
161186
<div class="flex flex-col gap-6">
162-
<div class="text-center flex justify-center items-center gap-1 opacity-80">
163-
Continuous Releases from
164-
<UIcon name="i-ph-git-branch" />
165-
{{ branch.name }}
166-
</div>
167-
168187
<div class="flex flex-col gap-2">
169188
<div
170189
v-for="commit of commitsWithRelease"
@@ -201,19 +220,40 @@ async function fetchMore() {
201220
</div>
202221
</div>
203222

204-
<div
205-
v-if="
206-
branch.target.history.pageInfo.hasNextPage && !fetchMoreForceDisabled
207-
"
208-
class="flex justify-center"
209-
>
223+
<div class="flex justify-center items-center gap-1 flex-wrap">
224+
<UButton
225+
color="neutral"
226+
variant="subtle"
227+
icon="i-ph-caret-left"
228+
:disabled="!hasPrevPage"
229+
:loading="fetching"
230+
@click="goPrevPage()"
231+
>
232+
Prev
233+
</UButton>
234+
235+
<template v-for="(item, index) in paginationItems" :key="`page-${index}`">
236+
<span v-if="item === '...'" class="px-2 text-sm opacity-60">…</span>
237+
<UButton
238+
v-else
239+
:color="item === currentPage ? 'primary' : 'neutral'"
240+
:variant="item === currentPage ? 'solid' : 'subtle'"
241+
:disabled="fetching"
242+
@click="fetchPage(item)"
243+
>
244+
{{ item }}
245+
</UButton>
246+
</template>
247+
210248
<UButton
211249
color="neutral"
212250
variant="subtle"
251+
icon="i-ph-caret-right"
252+
:disabled="!hasNextPage"
213253
:loading="fetching"
214-
@click="fetchMore()"
254+
@click="goNextPage()"
215255
>
216-
Load More
256+
Next
217257
</UButton>
218258
</div>
219259

0 commit comments

Comments
 (0)