fix(repo): paginate repo list alphabetically server-side

Switch from /search/repositories (best-match order) to /user/repos
with sort=full_name so infinite scroll appends in A–Z order instead
of injecting new pages into earlier letters.
This commit is contained in:
Julien Calixte
2026-05-16 23:59:04 +02:00
parent f3ed5e063f
commit 0a2445a06d

View File

@@ -12,7 +12,7 @@ const isReady = ref(false)
const isLoading = ref(false) const isLoading = ref(false)
const hasCredentialError = ref(false) const hasCredentialError = ref(false)
const currentPage = ref(0) const currentPage = ref(0)
const totalCount = ref(0) const hasMore = ref(true)
let lastFetchedAt = 0 let lastFetchedAt = 0
const { username, accessToken } = useGitHubLogin() const { username, accessToken } = useGitHubLogin()
@@ -20,7 +20,7 @@ const { username, accessToken } = useGitHubLogin()
const resetState = () => { const resetState = () => {
repos.value = [] repos.value = []
currentPage.value = 0 currentPage.value = 0
totalCount.value = 0 hasMore.value = true
isReady.value = false isReady.value = false
isLoading.value = false isLoading.value = false
hasCredentialError.value = false hasCredentialError.value = false
@@ -32,26 +32,26 @@ const loadMore = async () => {
isReady.value = true isReady.value = true
return return
} }
if (isLoading.value) return if (isLoading.value || !hasMore.value) return
isLoading.value = true isLoading.value = true
try { try {
const octokit = await getOctokit() const octokit = await getOctokit()
const nextPage = currentPage.value + 1 const nextPage = currentPage.value + 1
const repoList = await octokit.request("GET /search/repositories", { const repoList = await octokit.request("GET /user/repos", {
q: `user:${username.value}`, sort: "full_name",
direction: "asc",
affiliation: "owner",
per_page: PER_PAGE, per_page: PER_PAGE,
page: nextPage page: nextPage
}) })
currentPage.value = nextPage currentPage.value = nextPage
totalCount.value = repoList.data.total_count hasMore.value = repoList.data.length === PER_PAGE
const newItems = repoList.data.items.map((item) => ({ const newItems = repoList.data.map((item) => ({
id: `${item.id}`, id: `${item.id}`,
name: item.name, name: item.name,
isPrivate: item.private isPrivate: item.private ?? false
})) }))
repos.value = [...repos.value, ...newItems].sort((a, b) => repos.value = [...repos.value, ...newItems]
a.name < b.name ? -1 : 1
)
} catch (err: unknown) { } catch (err: unknown) {
if ( if (
typeof err === "object" && typeof err === "object" &&
@@ -79,9 +79,7 @@ watch(accessToken, (next, prev) => {
}) })
export const useRepos = () => { export const useRepos = () => {
const canLoadMore = computed( const canLoadMore = computed(() => !isLoading.value && hasMore.value)
() => !isLoading.value && repos.value.length < totalCount.value
)
const isStale = Date.now() - lastFetchedAt > STALE_TIME_MS const isStale = Date.now() - lastFetchedAt > STALE_TIME_MS
if (!isReady.value || isStale) { if (!isReady.value || isStale) {