feat: add loading state for async components (#1861)

This commit is contained in:
Phan An 2024-10-25 14:03:40 +07:00 committed by GitHub
parent 154b88e411
commit 54d5a6b493
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 40 additions and 4 deletions

View file

@ -39,9 +39,9 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { defineAsyncComponent, onMounted, ref, toRef } from 'vue' import { onMounted, ref, toRef } from 'vue'
import { isSong } from '@/utils/typeGuards' import { isSong } from '@/utils/typeGuards'
import { requireInjection } from '@/utils/helpers' import { defineAsyncComponent, requireInjection } from '@/utils/helpers'
import { preferenceStore } from '@/stores/preferenceStore' import { preferenceStore } from '@/stores/preferenceStore'
import { useRouter } from '@/composables/useRouter' import { useRouter } from '@/composables/useRouter'
import { useThirdPartyServices } from '@/composables/useThirdPartyServices' import { useThirdPartyServices } from '@/composables/useThirdPartyServices'

View file

@ -0,0 +1,27 @@
<template>
<div class="w-full pointer-events-none h-0.5 fixed z-50 top-0 left-0">
<div class="bg-k-highlight marquee absolute h-full w-1/3" />
</div>
<div class="w-full h-full skeleton p-4">
<div class="w-full h-full pulse rounded-md" />
</div>
</template>
<style lang="postcss">
@keyframes marquee {
from {
left: -50%;
}
to {
left: 100%;
}
}
.marquee {
animation: marquee 3s ease-in-out infinite;
@media (prefers-reduced-motion: reduce) {
animation: none;
}
}
</style>

View file

@ -1,12 +1,14 @@
import select from 'select' import select from 'select'
import { isObject, without } from 'lodash' import { isObject, without } from 'lodash'
import type { InjectionKey } from 'vue' import type { AsyncComponentLoader, Component, InjectionKey } from 'vue'
import { inject, isRef, provide, readonly, shallowReadonly } from 'vue' import { defineAsyncComponent as baseDefineAsyncComponent, inject, isRef, provide, readonly, shallowReadonly } from 'vue'
import type { ReadonlyInjectionKey } from '@/symbols' import type { ReadonlyInjectionKey } from '@/symbols'
import { logger } from '@/utils/logger' import { logger } from '@/utils/logger'
import { md5 } from '@/utils/crypto' import { md5 } from '@/utils/crypto'
import { isSong } from '@/utils/typeGuards' import { isSong } from '@/utils/typeGuards'
import LoadingComponent from '@/components/ui/skeletons/Loading.vue'
export const use = <T> (value: T | undefined | null, cb: (arg: T) => void) => { export const use = <T> (value: T | undefined | null, cb: (arg: T) => void) => {
if (typeof value === 'undefined' || value === null) { if (typeof value === 'undefined' || value === null) {
return return
@ -113,3 +115,10 @@ export const copyText = async (text: string) => {
export const getPlayableProp = <T> (playable: Playable, songKey: keyof Song, episodeKey: keyof Episode): T => { export const getPlayableProp = <T> (playable: Playable, songKey: keyof Song, episodeKey: keyof Episode): T => {
return isSong(playable) ? playable[songKey] : playable[episodeKey] return isSong(playable) ? playable[songKey] : playable[episodeKey]
} }
export const defineAsyncComponent = (loader: AsyncComponentLoader, loadingComponent?: Component) => {
return baseDefineAsyncComponent({
loader,
loadingComponent: loadingComponent || LoadingComponent,
})
}