chore: make GlobalEventListener renderless (#1560)

This commit is contained in:
Phan An 2022-10-27 15:33:32 +02:00 committed by GitHub
parent 30f9ef4555
commit cadc2d1d92
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 56 additions and 54 deletions

View file

@ -39,7 +39,7 @@ import Overlay from '@/components/ui/Overlay.vue'
import AppFooter from '@/components/layout/app-footer/index.vue' import AppFooter from '@/components/layout/app-footer/index.vue'
// GlobalEventListener must NOT be lazy-loaded, so that it can handle LOG_OUT event properly. // GlobalEventListener must NOT be lazy-loaded, so that it can handle LOG_OUT event properly.
import GlobalEventListeners from '@/components/utils/GlobalEventListeners.vue' import { GlobalEventListeners } from '@/components/utils/GlobalEventListeners'
const Hotkeys = defineAsyncComponent(() => import('@/components/utils/HotkeyListener.vue')) const Hotkeys = defineAsyncComponent(() => import('@/components/utils/HotkeyListener.vue'))
const LoginForm = defineAsyncComponent(() => import('@/components/auth/LoginForm.vue')) const LoginForm = defineAsyncComponent(() => import('@/components/auth/LoginForm.vue'))

View file

@ -21,7 +21,7 @@ new class extends UnitTestCase {
ExtraPanelTabHeader: this.stub() ExtraPanelTabHeader: this.stub()
}, },
provide: { provide: {
[CurrentSongKey]: songRef [<symbol>CurrentSongKey]: songRef
} }
} }
}) })

View file

@ -30,8 +30,8 @@ new class extends UnitTestCase {
}) })
await waitFor(() => { await waitFor(() => {
expect(fetchGenreMock).toHaveBeenCalledWith(genre.name) expect(fetchGenreMock).toHaveBeenCalledWith(genre!.name)
expect(paginateMock).toHaveBeenCalledWith(genre.name, 'title', 'asc', 1) expect(paginateMock).toHaveBeenCalledWith(genre!.name, 'title', 'asc', 1)
}) })
await this.tick(2) await this.tick(2)

View file

@ -13,7 +13,7 @@ new class extends UnitTestCase {
return this.render(FooterPlayButton, { return this.render(FooterPlayButton, {
global: { global: {
provide: { provide: {
[CurrentSongKey]: ref(currentSong) [<symbol>CurrentSongKey]: ref(currentSong)
} }
} }
}) })
@ -40,7 +40,7 @@ new class extends UnitTestCase {
const playMock = this.mock(playbackService, 'queueAndPlay') const playMock = this.mock(playbackService, 'queueAndPlay')
const goMock = this.mock(this.router, 'go') const goMock = this.mock(this.router, 'go')
this.router.activateRoute({ await this.router.activateRoute({
screen, screen,
path: '_' path: '_'
}, { id: '42' }) }, { id: '42' })
@ -65,7 +65,7 @@ new class extends UnitTestCase {
const playMock = this.mock(playbackService, 'queueAndPlay') const playMock = this.mock(playbackService, 'queueAndPlay')
const goMock = this.mock(this.router, 'go') const goMock = this.mock(this.router, 'go')
this.router.activateRoute({ await this.router.activateRoute({
screen, screen,
path: '_' path: '_'
}) })
@ -87,7 +87,7 @@ new class extends UnitTestCase {
const playMock = this.mock(playbackService, 'queueAndPlay') const playMock = this.mock(playbackService, 'queueAndPlay')
const goMock = this.mock(this.router, 'go') const goMock = this.mock(this.router, 'go')
this.router.activateRoute({ await this.router.activateRoute({
screen, screen,
path: '_' path: '_'
}) })
@ -108,7 +108,7 @@ new class extends UnitTestCase {
const playMock = this.mock(playbackService, 'queueAndPlay') const playMock = this.mock(playbackService, 'queueAndPlay')
const goMock = this.mock(this.router, 'go') const goMock = this.mock(this.router, 'go')
this.router.activateRoute({ await this.router.activateRoute({
screen: 'Songs', screen: 'Songs',
path: '_' path: '_'
}) })

View file

@ -0,0 +1,46 @@
/**
* Global event listeners (basically, those without a Vue instance access) go here.
*/
import { defineComponent } from 'vue'
import { authService } from '@/services'
import { playlistFolderStore, playlistStore, userStore } from '@/stores'
import { eventBus, forceReloadWindow, requireInjection } from '@/utils'
import { DialogBoxKey, MessageToasterKey, RouterKey } from '@/symbols'
export const GlobalEventListeners = defineComponent({
setup (props, { slots }) {
const toaster = requireInjection(MessageToasterKey)
const dialog = requireInjection(DialogBoxKey)
const router = requireInjection(RouterKey)
eventBus.on({
PLAYLIST_DELETE: async (playlist: Playlist) => {
if (await dialog.value.confirm(`Delete the playlist "${playlist.name}"?`)) {
await playlistStore.delete(playlist)
toaster.value.success(`Playlist "${playlist.name}" deleted.`)
router.go('home')
}
},
PLAYLIST_FOLDER_DELETE: async (folder: PlaylistFolder) => {
if (await dialog.value.confirm(`Delete the playlist folder "${folder.name}"?`)) {
await playlistFolderStore.delete(folder)
toaster.value.success(`Playlist folder "${folder.name}" deleted.`)
router.go('home')
}
},
/**
* Log the current user out and reset the application state.
*/
LOG_OUT: async () => {
await userStore.logout()
authService.destroy()
forceReloadWindow()
}
})
return () => slots.default?.()
}
})

View file

@ -1,44 +0,0 @@
<template>
<span></span>
</template>
<script lang="ts" setup>
/**
* Global event listeners (basically, those without a Vue instance access) go here.
*/
import { authService } from '@/services'
import { playlistFolderStore, playlistStore, userStore } from '@/stores'
import { eventBus, forceReloadWindow, requireInjection } from '@/utils'
import { DialogBoxKey, MessageToasterKey, RouterKey } from '@/symbols'
const toaster = requireInjection(MessageToasterKey)
const dialog = requireInjection(DialogBoxKey)
const router = requireInjection(RouterKey)
eventBus.on({
PLAYLIST_DELETE: async (playlist: Playlist) => {
if (await dialog.value.confirm(`Delete the playlist "${playlist.name}"?`)) {
await playlistStore.delete(playlist)
toaster.value.success(`Playlist "${playlist.name}" deleted.`)
router.go('home')
}
},
PLAYLIST_FOLDER_DELETE: async (folder: PlaylistFolder) => {
if (await dialog.value.confirm(`Delete the playlist folder "${folder.name}"?`)) {
await playlistFolderStore.delete(folder)
toaster.value.success(`Playlist folder "${folder.name}" deleted.`)
router.go('home')
}
},
/**
* Log the current user out and reset the application state.
*/
LOG_OUT: async () => {
await userStore.logout()
authService.destroy()
forceReloadWindow()
}
})
</script>

View file

@ -105,6 +105,6 @@ export const tooltip: Directive = {
beforeUnmount: (el: ElementWithTooltip, binding) => { beforeUnmount: (el: ElementWithTooltip, binding) => {
el.$cleanup && el.$cleanup() el.$cleanup && el.$cleanup()
el.$tooltip && document.removeChild(el.$tooltip) el.$tooltip && document.body.removeChild(el.$tooltip)
} }
} }