Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(nuxt): custom loading reset/hide delay + force finish() #25932

Merged
merged 12 commits into from
Mar 6, 2024
34 changes: 27 additions & 7 deletions packages/nuxt/src/app/composables/loading-indicator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
duration: number
/** @default 200 */
throttle: number
/** @default 500 */
hideDelay: number
/** @default 400 */
resetDelay: number
/**
* You can provide a custom function to customize the progress estimation,
* which is a function that receives the duration of the loading bar (above)
Expand All @@ -15,12 +19,19 @@
estimatedProgress?: (duration: number, elapsed: number) => number
}

function _hide (isLoading: Ref<boolean>, progress: Ref<number>) {
function _hide (isLoading: Ref<boolean>, progress: Ref<number>, hideDelay: number, resetDelay: number) {
if (import.meta.client) {
setTimeout(() => {
isLoading.value = false
setTimeout(() => { progress.value = 0 }, 400)
}, 500)
setTimeout(() => { progress.value = 0 }, resetDelay)
}, hideDelay)
}
}

function _reset (isLoading: Ref<boolean>, progress: Ref<number>) {
if (import.meta.client) {
isLoading.value = false
progress.value = 0
}
}

Expand All @@ -40,7 +51,7 @@
}

function createLoadingIndicator (opts: Partial<LoadingIndicatorOpts> = {}) {
const { duration = 2000, throttle = 200 } = opts
const { duration = 2000, throttle = 200, hideDelay = 500, resetDelay = 400 } = opts
const getProgress = opts.estimatedProgress || defaultEstimatedProgress
const nuxtApp = useNuxtApp()
const progress = ref(0)
Expand All @@ -50,7 +61,12 @@

let _throttle: any = null

const start = () => set(0)
const start = (force: boolean | null = true) => {
danielroe marked this conversation as resolved.
Show resolved Hide resolved
if (force) {
_reset(isLoading, progress)
}
set(0)
}

function set (at = 0) {
if (nuxtApp.isHydrating) {
Expand All @@ -70,11 +86,15 @@
}
}

function finish () {
function finish (force: boolean | null = false) {
progress.value = 100
done = true
clear()
_hide(isLoading, progress)
if(force) {
_reset(isLoading, progress)
} else {
_hide(isLoading, progress, hideDelay, resetDelay)
}
}

function clear () {
Expand Down Expand Up @@ -113,7 +133,7 @@
const unsubLoadingFinishHook = nuxtApp.hook('page:loading:end', () => {
finish()
})
const unsubError = nuxtApp.hook('vue:error', finish)

Check failure on line 136 in packages/nuxt/src/app/composables/loading-indicator.ts

View workflow job for this annotation

GitHub Actions / build

Argument of type '(force?: boolean | null) => void' is not assignable to parameter of type '(err: unknown, instance: ComponentPublicInstance<{}, {}, {}, {}, {}, {}, {}, {}, false, ComponentOptionsBase<any, any, any, any, any, any, any, any, any, {}, {}, string, {}>, {}, {}> | null, info: string) => HookResult'.

_cleanup = () => {
unsubError()
Expand Down
14 changes: 14 additions & 0 deletions test/nuxt/composables.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,20 @@ describe('loading state', () => {
})
})

describe('loading state', () => {
it('expect loading state to be changed by force starting/stoping', async () => {
vi.stubGlobal('setTimeout', vi.fn((cb: Function) => cb()))
const nuxtApp = useNuxtApp()
const { isLoading, start, finish } = useLoadingIndicator({ resetDelay: 0, hideDelay: 0 })
expect(isLoading.value).toBeFalsy()
await nuxtApp.callHook('page:loading:start')
expect(isLoading.value).toBeTruthy()
start(true)
finish(true)
expect(isLoading.value).toBeFalsy()
})
})

describe.skipIf(process.env.TEST_MANIFEST === 'manifest-off')('app manifests', () => {
it('getAppManifest', async () => {
const manifest = await getAppManifest()
Expand Down