Compare commits

3 Commits

Author SHA1 Message Date
Julien Calixte
4fd72226ff refactor(repos): redesign RepoList in editorial style
Align the repo manager with WelcomeWorld and PublicNoteView: editorial
top nav, serif hero, pastel favorite tiles, A-Z grouped list, skeleton
and credential-error states, and a name filter.
2026-05-14 16:13:41 +02:00
Julien Calixte
816c3687d8 fix(auth): clear stale credential error after github re-auth
The 401 flag and cached repo list were module-level and only reset
after a 20-min stale window, so re-authenticating left the
"credentials are invalid or expired" message pinned on. Watch the
access token: reset state and refetch on change. Also await
saveCredentials before redirecting so refs are settled.
2026-05-14 13:04:44 +02:00
Julien Calixte
f2f2a3114b style: no more underline for header tag 2026-05-14 01:22:46 +02:00
4 changed files with 1105 additions and 138 deletions

View File

@@ -19,8 +19,7 @@ onBeforeMount(async () => {
if ("error" in token) { if ("error" in token) {
hasError.value = true hasError.value = true
} else { } else {
token.access_token await saveCredentials(token)
saveCredentials(token)
} }
router.replace({ name: "Home" }) router.replace({ name: "Home" })

View File

@@ -1,4 +1,4 @@
import { computed, ref } from "vue" import { computed, ref, watch } from "vue"
import { useGitHubLogin } from "@/hooks/useGitHubLogin.hook" import { useGitHubLogin } from "@/hooks/useGitHubLogin.hook"
import { RepoBase } from "@/modules/repo/interfaces/RepoBase" import { RepoBase } from "@/modules/repo/interfaces/RepoBase"
@@ -15,9 +15,18 @@ const currentPage = ref(0)
const totalCount = ref(0) const totalCount = ref(0)
let lastFetchedAt = 0 let lastFetchedAt = 0
export const useRepos = () => {
const { username, accessToken } = useGitHubLogin() const { username, accessToken } = useGitHubLogin()
const resetState = () => {
repos.value = []
currentPage.value = 0
totalCount.value = 0
isReady.value = false
isLoading.value = false
hasCredentialError.value = false
lastFetchedAt = 0
}
const loadMore = async () => { const loadMore = async () => {
if (!accessToken.value || !username.value) { if (!accessToken.value || !username.value) {
isReady.value = true isReady.value = true
@@ -60,6 +69,16 @@ export const useRepos = () => {
} }
} }
watch(accessToken, (next, prev) => {
if (next === prev) return
resetState()
if (next && username.value) {
lastFetchedAt = Date.now()
loadMore()
}
})
export const useRepos = () => {
const canLoadMore = computed( const canLoadMore = computed(
() => !isLoading.value && repos.value.length < totalCount.value () => !isLoading.value && repos.value.length < totalCount.value
) )
@@ -67,12 +86,7 @@ export const useRepos = () => {
const isStale = Date.now() - lastFetchedAt > STALE_TIME_MS const isStale = Date.now() - lastFetchedAt > STALE_TIME_MS
if (!isReady.value || isStale) { if (!isReady.value || isStale) {
if (isStale && isReady.value) { if (isStale && isReady.value) {
repos.value = [] resetState()
currentPage.value = 0
totalCount.value = 0
isReady.value = false
isLoading.value = false
hasCredentialError.value = false
} }
lastFetchedAt = Date.now() lastFetchedAt = Date.now()
loadMore() loadMore()

View File

@@ -109,6 +109,10 @@ a {
a.title-stacked-note-link { a.title-stacked-note-link {
display: block; display: block;
overflow: visible; overflow: visible;
&:hover {
cursor: pointer;
text-decoration: none;
}
} }
.title-stacked-note ul, .title-stacked-note ul,

File diff suppressed because it is too large Load Diff