feat: shared loading state + cleanup loading state management (#5835)
* feat: implement shared loading bar component and polished loading states across the app * feat: align loading states + ensureQueryData changes * fix: lint + bugs * fix: skeleton for manage servers page * fix: merge conflict fix
This commit is contained in:
@@ -38,6 +38,7 @@ import {
|
||||
CreationFlowModal,
|
||||
defineMessages,
|
||||
I18nDebugPanel,
|
||||
LoadingBar,
|
||||
NewsArticleCard,
|
||||
NotificationPanel,
|
||||
OverflowMenu,
|
||||
@@ -52,7 +53,7 @@ import {
|
||||
useVIntl,
|
||||
} from '@modrinth/ui'
|
||||
import { formatBytes, renderString } from '@modrinth/utils'
|
||||
import { useQuery } from '@tanstack/vue-query'
|
||||
import { useQuery, useQueryClient } from '@tanstack/vue-query'
|
||||
import { getVersion } from '@tauri-apps/api/app'
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
import { getCurrentWindow } from '@tauri-apps/api/window'
|
||||
@@ -65,7 +66,6 @@ import { computed, onMounted, onUnmounted, provide, ref, watch } from 'vue'
|
||||
import { RouterView, useRoute, useRouter } from 'vue-router'
|
||||
|
||||
import ModrinthAppLogo from '@/assets/modrinth_app.svg?component'
|
||||
import ModrinthLoadingIndicator from '@/components/LoadingIndicatorBar.vue'
|
||||
import AccountsCard from '@/components/ui/AccountsCard.vue'
|
||||
import Breadcrumbs from '@/components/ui/Breadcrumbs.vue'
|
||||
import ErrorModal from '@/components/ui/ErrorModal.vue'
|
||||
@@ -113,8 +113,9 @@ import {
|
||||
import { createServerInstall, provideServerInstall } from '@/providers/server-install'
|
||||
import { setupProviders } from '@/providers/setup'
|
||||
import { setupAuthProvider } from '@/providers/setup/auth'
|
||||
import { setupLoadingStateProvider } from '@/providers/setup/loading-state'
|
||||
import { useError } from '@/store/error.js'
|
||||
import { useLoading, useTheming } from '@/store/state'
|
||||
import { useTheming } from '@/store/state'
|
||||
|
||||
import { generateSkinPreviews } from './helpers/rendering/batch-skin-renderer'
|
||||
import { get_available_capes, get_available_skins } from './helpers/skins'
|
||||
@@ -420,9 +421,11 @@ const handleClose = async () => {
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
const loading = useLoading()
|
||||
const loading = setupLoadingStateProvider()
|
||||
loading.setEnabled(false)
|
||||
loading.startLoading()
|
||||
let initialLoadToken = loading.begin()
|
||||
let routerToken = null
|
||||
let suspenseToken = null
|
||||
|
||||
let suspensePending = false
|
||||
|
||||
@@ -435,7 +438,8 @@ const sidebarOverlayScrollbarsOptions = Object.freeze({
|
||||
|
||||
router.beforeEach(() => {
|
||||
suspensePending = false
|
||||
loading.startLoading()
|
||||
if (routerToken) loading.end(routerToken)
|
||||
routerToken = loading.begin()
|
||||
})
|
||||
router.afterEach((to, from, failure) => {
|
||||
trackEvent('PageView', {
|
||||
@@ -445,11 +449,83 @@ router.afterEach((to, from, failure) => {
|
||||
})
|
||||
setTimeout(() => {
|
||||
if (!suspensePending && stateInitialized.value) {
|
||||
loading.stopLoading()
|
||||
if (initialLoadToken) {
|
||||
loading.end(initialLoadToken)
|
||||
initialLoadToken = null
|
||||
}
|
||||
if (routerToken) {
|
||||
loading.end(routerToken)
|
||||
routerToken = null
|
||||
}
|
||||
}
|
||||
}, 100)
|
||||
})
|
||||
|
||||
function onSuspensePending() {
|
||||
suspensePending = true
|
||||
if (suspenseToken) loading.end(suspenseToken)
|
||||
suspenseToken = loading.begin()
|
||||
}
|
||||
|
||||
function onSuspenseResolve() {
|
||||
if (suspenseToken) {
|
||||
loading.end(suspenseToken)
|
||||
suspenseToken = null
|
||||
}
|
||||
if (routerToken) {
|
||||
loading.end(routerToken)
|
||||
routerToken = null
|
||||
}
|
||||
}
|
||||
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
watch(stateInitialized, (ready) => {
|
||||
if (ready) {
|
||||
if (initialLoadToken) {
|
||||
loading.end(initialLoadToken)
|
||||
initialLoadToken = null
|
||||
}
|
||||
if (routerToken) {
|
||||
loading.end(routerToken)
|
||||
routerToken = null
|
||||
}
|
||||
|
||||
queryClient.prefetchQuery({
|
||||
queryKey: ['servers'],
|
||||
queryFn: async () => {
|
||||
const response = await tauriApiClient.archon.servers_v0.list({ limit: 100 })
|
||||
const hasMedalServers = response.servers.some((s) => s.is_medal)
|
||||
if (hasMedalServers) {
|
||||
const subscriptions = await tauriApiClient.labrinth.billing_internal.getSubscriptions()
|
||||
for (const server of response.servers) {
|
||||
if (server.is_medal) {
|
||||
const sub = subscriptions.find((s) => s.metadata?.id === server.server_id)
|
||||
if (sub) {
|
||||
server.medal_expires = new Date(
|
||||
new Date(sub.created).getTime() + 5 * 86400000,
|
||||
).toISOString()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return response
|
||||
},
|
||||
staleTime: 30_000,
|
||||
})
|
||||
queryClient.prefetchQuery({
|
||||
queryKey: ['billing', 'subscriptions'],
|
||||
queryFn: () => tauriApiClient.labrinth.billing_internal.getSubscriptions(),
|
||||
staleTime: 30_000,
|
||||
})
|
||||
queryClient.prefetchQuery({
|
||||
queryKey: ['billing', 'payments'],
|
||||
queryFn: () => tauriApiClient.labrinth.billing_internal.getPayments(),
|
||||
staleTime: 30_000,
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
const error = useError()
|
||||
const errorModal = ref()
|
||||
const minecraftAuthErrorModal = ref()
|
||||
@@ -1236,7 +1312,7 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
|
||||
width: 'calc(100% - var(--left-bar-width) - var(--right-bar-width))',
|
||||
}"
|
||||
>
|
||||
<ModrinthLoadingIndicator />
|
||||
<LoadingBar position="absolute" />
|
||||
</div>
|
||||
<div
|
||||
v-if="themeStore.featureFlags.page_path"
|
||||
@@ -1272,19 +1348,7 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
|
||||
</Admonition>
|
||||
<RouterView v-slot="{ Component }">
|
||||
<template v-if="Component">
|
||||
<Suspense
|
||||
@pending="
|
||||
() => {
|
||||
suspensePending = true
|
||||
loading.startLoading()
|
||||
}
|
||||
"
|
||||
@resolve="
|
||||
() => {
|
||||
loading.stopLoading()
|
||||
}
|
||||
"
|
||||
>
|
||||
<Suspense @pending="onSuspensePending" @resolve="onSuspenseResolve">
|
||||
<component :is="Component"></component>
|
||||
</Suspense>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user