mirror of
https://github.com/koel/koel
synced 2024-11-10 06:34:14 +00:00
feat: make event bus (emitter) type-safe (#1591)
This commit is contained in:
parent
02c5e79dac
commit
5992fda776
24 changed files with 125 additions and 234 deletions
|
@ -32,6 +32,7 @@
|
|||
"sketch-js": "^1.1.3",
|
||||
"slugify": "^1.0.2",
|
||||
"three": "^0.146.0",
|
||||
"tiny-typed-emitter": "^2.1.0",
|
||||
"vue": "^3.2.32",
|
||||
"vue-global-events": "^2.1.1",
|
||||
"youtube-player": "^3.0.4"
|
||||
|
|
|
@ -48,7 +48,7 @@ const viewAlbumDetails = () => trigger(() => router.go(`album/${album.value!.id}
|
|||
const viewArtistDetails = () => trigger(() => router.go(`artist/${album.value!.artist_id}`))
|
||||
const download = () => trigger(() => downloadService.fromAlbum(album.value!))
|
||||
|
||||
eventBus.on('ALBUM_CONTEXT_MENU_REQUESTED', async (e: MouseEvent, _album: Album) => {
|
||||
eventBus.on('ALBUM_CONTEXT_MENU_REQUESTED', async (e, _album) => {
|
||||
album.value = _album
|
||||
await open(e.pageY, e.pageX, { album })
|
||||
})
|
||||
|
|
|
@ -47,7 +47,7 @@ const shuffle = () => trigger(async () => {
|
|||
const viewArtistDetails = () => trigger(() => router.go(`artist/${artist.value!.id}`))
|
||||
const download = () => trigger(() => downloadService.fromArtist(artist.value!))
|
||||
|
||||
eventBus.on('ARTIST_CONTEXT_MENU_REQUESTED', async (e: MouseEvent, _artist: Artist) => {
|
||||
eventBus.on('ARTIST_CONTEXT_MENU_REQUESTED', async (e, _artist) => {
|
||||
artist.value = _artist
|
||||
await open(e.pageY, e.pageX, { _artist })
|
||||
})
|
||||
|
|
|
@ -46,36 +46,29 @@ watch(activeModalName, name => name ? dialog.value?.showModal() : dialog.value?.
|
|||
|
||||
const close = () => (activeModalName.value = null)
|
||||
|
||||
eventBus.on({
|
||||
MODAL_SHOW_ABOUT_KOEL: () => (activeModalName.value = 'about-koel'),
|
||||
MODAL_SHOW_ADD_USER_FORM: () => (activeModalName.value = 'add-user-form'),
|
||||
MODAL_SHOW_CREATE_PLAYLIST_FORM: () => (activeModalName.value = 'create-playlist-form'),
|
||||
MODAL_SHOW_CREATE_SMART_PLAYLIST_FORM: () => (activeModalName.value = 'create-smart-playlist-form'),
|
||||
MODAL_SHOW_CREATE_PLAYLIST_FOLDER_FORM: () => (activeModalName.value = 'create-playlist-folder-form'),
|
||||
|
||||
MODAL_SHOW_EDIT_PLAYLIST_FORM: (playlist: Playlist) => {
|
||||
eventBus.on('MODAL_SHOW_ABOUT_KOEL', () => (activeModalName.value = 'about-koel'))
|
||||
.on('MODAL_SHOW_ADD_USER_FORM', () => (activeModalName.value = 'add-user-form'))
|
||||
.on('MODAL_SHOW_CREATE_PLAYLIST_FORM', () => (activeModalName.value = 'create-playlist-form'))
|
||||
.on('MODAL_SHOW_CREATE_SMART_PLAYLIST_FORM', () => (activeModalName.value = 'create-smart-playlist-form'))
|
||||
.on('MODAL_SHOW_CREATE_PLAYLIST_FOLDER_FORM', () => (activeModalName.value = 'create-playlist-folder-form'))
|
||||
.on('MODAL_SHOW_EDIT_PLAYLIST_FORM', playlist => {
|
||||
playlistToEdit.value = playlist
|
||||
activeModalName.value = playlist.is_smart ? 'edit-smart-playlist-form' : 'edit-playlist-form'
|
||||
},
|
||||
|
||||
MODAL_SHOW_EDIT_USER_FORM: (user: User) => {
|
||||
})
|
||||
.on('MODAL_SHOW_EDIT_USER_FORM', user => {
|
||||
userToEdit.value = user
|
||||
activeModalName.value = 'edit-user-form'
|
||||
},
|
||||
|
||||
MODAL_SHOW_EDIT_SONG_FORM: (songs: Song | Song[], initialTab: EditSongFormTabName = 'details') => {
|
||||
})
|
||||
.on('MODAL_SHOW_EDIT_SONG_FORM', (songs, initialTab: EditSongFormTabName = 'details') => {
|
||||
songsToEdit.value = arrayify(songs)
|
||||
editSongFormInitialTab.value = initialTab
|
||||
activeModalName.value = 'edit-song-form'
|
||||
},
|
||||
|
||||
MODAL_SHOW_EDIT_PLAYLIST_FOLDER_FORM: (folder: PlaylistFolder) => {
|
||||
})
|
||||
.on('MODAL_SHOW_EDIT_PLAYLIST_FOLDER_FORM', folder => {
|
||||
playlistFolderToEdit.value = folder
|
||||
activeModalName.value = 'edit-playlist-folder-form'
|
||||
},
|
||||
|
||||
MODAL_SHOW_EQUALIZER: () => (activeModalName.value = 'equalizer')
|
||||
})
|
||||
})
|
||||
.on('MODAL_SHOW_EQUALIZER', () => (activeModalName.value = 'equalizer'))
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
@ -145,13 +145,11 @@ router.onRouteChanged(route => {
|
|||
activeScreen.value = route.screen
|
||||
})
|
||||
|
||||
eventBus.on({
|
||||
/**
|
||||
* Listen to toggle sidebar event to show or hide the sidebar.
|
||||
* This should only be triggered on a mobile device.
|
||||
*/
|
||||
TOGGLE_SIDEBAR: () => (mobileShowing.value = !mobileShowing.value)
|
||||
})
|
||||
/**
|
||||
* Listen to toggle sidebar event to show or hide the sidebar.
|
||||
* This should only be triggered on a mobile device.
|
||||
*/
|
||||
eventBus.on('TOGGLE_SIDEBAR', () => (mobileShowing.value = !mobileShowing.value))
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
import { useContextMenu } from '@/composables'
|
||||
import { eventBus } from '@/utils'
|
||||
import { EventName } from '@/config'
|
||||
import { onMounted } from 'vue'
|
||||
|
||||
const { base, ContextMenuBase, open, trigger } = useContextMenu()
|
||||
|
||||
|
@ -24,9 +23,5 @@ const actionToEventMap: Record<string, EventName> = {
|
|||
|
||||
const onItemClicked = (key: keyof typeof actionToEventMap) => trigger(() => eventBus.emit(actionToEventMap[key]))
|
||||
|
||||
onMounted(() => {
|
||||
eventBus.on('CREATE_NEW_PLAYLIST_CONTEXT_MENU_REQUESTED', async (e: MouseEvent) => {
|
||||
await open(e.pageY, e.pageX)
|
||||
})
|
||||
})
|
||||
eventBus.on('CREATE_NEW_PLAYLIST_CONTEXT_MENU_REQUESTED', async e => await open(e.pageY, e.pageX))
|
||||
</script>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { ref } from 'vue'
|
||||
import { eventBus } from '@/utils'
|
||||
import { useContextMenu } from '@/composables'
|
||||
|
||||
|
@ -18,10 +18,8 @@ const playlist = ref<Playlist>()
|
|||
const editPlaylist = () => trigger(() => eventBus.emit('MODAL_SHOW_EDIT_PLAYLIST_FORM', playlist.value))
|
||||
const deletePlaylist = () => trigger(() => eventBus.emit('PLAYLIST_DELETE', playlist.value))
|
||||
|
||||
onMounted(() => {
|
||||
eventBus.on('PLAYLIST_CONTEXT_MENU_REQUESTED', async (event: MouseEvent, _playlist: Playlist) => {
|
||||
playlist.value = _playlist
|
||||
await open(event.pageY, event.pageX, { playlist })
|
||||
})
|
||||
eventBus.on('PLAYLIST_CONTEXT_MENU_REQUESTED', async (event, _playlist) => {
|
||||
playlist.value = _playlist
|
||||
await open(event.pageY, event.pageX, { playlist })
|
||||
})
|
||||
</script>
|
||||
|
|
|
@ -42,7 +42,7 @@ const shuffle = () => trigger(async () => {
|
|||
const rename = () => trigger(() => eventBus.emit('MODAL_SHOW_EDIT_PLAYLIST_FOLDER_FORM', folder.value))
|
||||
const destroy = () => trigger(() => eventBus.emit('PLAYLIST_FOLDER_DELETE', folder.value))
|
||||
|
||||
eventBus.on('PLAYLIST_FOLDER_CONTEXT_MENU_REQUESTED', async (e: MouseEvent, _folder: PlaylistFolder) => {
|
||||
eventBus.on('PLAYLIST_FOLDER_CONTEXT_MENU_REQUESTED', async (e, _folder) => {
|
||||
folder.value = _folder
|
||||
await open(e.pageY, e.pageX, { folder })
|
||||
})
|
||||
|
|
|
@ -75,7 +75,8 @@ const libraryEmpty = computed(() => commonStore.state.song_length === 0)
|
|||
const loading = ref(false)
|
||||
let initialized = false
|
||||
|
||||
eventBus.on(['SONGS_DELETED', 'SONGS_UPDATED'], () => overviewStore.refresh())
|
||||
eventBus.on('SONGS_DELETED', () => overviewStore.refresh())
|
||||
.on('SONGS_UPDATED', () => overviewStore.refresh())
|
||||
|
||||
useScreen('Home').onScreenActivated(async () => {
|
||||
if (!initialized) {
|
||||
|
|
|
@ -135,11 +135,9 @@ watch(playlistId, async id => {
|
|||
|
||||
router.onRouteChanged(route => route.screen === 'Playlist' && (playlistId.value = parseInt(route.params!.id)))
|
||||
|
||||
eventBus.on({
|
||||
PLAYLIST_UPDATED: async (updated: Playlist) => updated.id === playlistId.value && await fetchSongs(),
|
||||
PLAYLIST_SONGS_REMOVED: async (playlist: Playlist, removed: Song[]) => {
|
||||
eventBus.on('PLAYLIST_UPDATED', async updated => updated.id === playlistId.value && await fetchSongs())
|
||||
.on('PLAYLIST_SONGS_REMOVED', async (playlist, removed) => {
|
||||
if (playlist.id !== playlistId.value) return
|
||||
songs.value = differenceBy(songs.value, removed, 'id')
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
|
|
@ -109,7 +109,7 @@ const removeSelected = () => selectedSongs.value.length && queueStore.unqueue(se
|
|||
const onPressEnter = () => selectedSongs.value.length && playbackService.play(selectedSongs.value[0])
|
||||
const onReorder = (target: Song) => queueStore.move(selectedSongs.value, target)
|
||||
|
||||
eventBus.on('SONG_QUEUED_FROM_ROUTE', async (id: string) => {
|
||||
eventBus.on('SONG_QUEUED_FROM_ROUTE', async id => {
|
||||
let song: Song | undefined
|
||||
|
||||
try {
|
||||
|
@ -127,7 +127,7 @@ eventBus.on('SONG_QUEUED_FROM_ROUTE', async (id: string) => {
|
|||
loading.value = false
|
||||
}
|
||||
|
||||
queueStore.queueIfNotQueued(song)
|
||||
await playbackService.play(song)
|
||||
queueStore.queueIfNotQueued(song!)
|
||||
await playbackService.play(song!)
|
||||
})
|
||||
</script>
|
||||
|
|
|
@ -26,7 +26,7 @@ import { CurrentSongKey } from '@/symbols'
|
|||
import ScreenHeader from '@/components/ui/ScreenHeader.vue'
|
||||
import ScreenEmptyState from '@/components/ui/ScreenEmptyState.vue'
|
||||
|
||||
let player: YouTubePlayer | null = null
|
||||
let player: YouTubePlayer
|
||||
const title = ref('YouTube Video')
|
||||
|
||||
const getPlayer = () => {
|
||||
|
@ -50,7 +50,7 @@ const currentSong = requireInjection(CurrentSongKey)
|
|||
*/
|
||||
watch(() => currentSong.value?.playback_state, state => state === 'Playing' && player?.pauseVideo())
|
||||
|
||||
eventBus.on('PLAY_YOUTUBE_VIDEO', (payload: { id: string, title: string }) => {
|
||||
eventBus.on('PLAY_YOUTUBE_VIDEO', payload => {
|
||||
title.value = payload.title
|
||||
|
||||
use(getPlayer(), player => {
|
||||
|
|
|
@ -113,16 +113,12 @@ const doSearch = async () => {
|
|||
searching.value = false
|
||||
}
|
||||
|
||||
eventBus.on({
|
||||
SEARCH_KEYWORDS_CHANGED: async (_q: string) => {
|
||||
q.value = _q
|
||||
eventBus.on('SEARCH_KEYWORDS_CHANGED', async _q => {
|
||||
q.value = _q
|
||||
await doSearch()
|
||||
}).on('SONGS_DELETED', async songs => {
|
||||
if (intersectionBy(songs, excerpt.value.songs, 'id').length !== 0) {
|
||||
await doSearch()
|
||||
},
|
||||
|
||||
SONGS_DELETED: async (songs: Song[]) => {
|
||||
if (intersectionBy(songs, excerpt.value.songs, 'id').length !== 0) {
|
||||
await doSearch()
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
|
|
@ -150,7 +150,7 @@ const deleteFromFilesystem = () => trigger(async () => {
|
|||
}
|
||||
})
|
||||
|
||||
eventBus.on('SONG_CONTEXT_MENU_REQUESTED', async (e: MouseEvent, _songs: Song | Song[]) => {
|
||||
eventBus.on('SONG_CONTEXT_MENU_REQUESTED', async (e, _songs) => {
|
||||
songs.value = arrayify(_songs)
|
||||
await open(e.pageY, e.pageX, { songs: songs.value })
|
||||
})
|
||||
|
|
|
@ -88,9 +88,7 @@ const open = async (_top = 0, _left = 0) => {
|
|||
eventBus.emit('CONTEXT_MENU_OPENED', el)
|
||||
}
|
||||
|
||||
const close = () => {
|
||||
shown.value = false
|
||||
}
|
||||
const close = () => (shown.value = false)
|
||||
|
||||
// ensure there's only one context menu at any time
|
||||
eventBus.on('CONTEXT_MENU_OPENED', target => target === el || close())
|
||||
|
|
|
@ -35,10 +35,8 @@ const show = (options: Partial<OverlayState>) => {
|
|||
|
||||
const hide = () => (state.showing = false)
|
||||
|
||||
eventBus.on({
|
||||
SHOW_OVERLAY: show,
|
||||
HIDE_OVERLAY: hide
|
||||
})
|
||||
eventBus.on('SHOW_OVERLAY', options => show(options))
|
||||
.on('HIDE_OVERLAY', () => hide())
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
|
|
@ -55,11 +55,9 @@ const onSubmit = () => {
|
|||
|
||||
const maybeGoToSearchScreen = () => isMobile.any || router.go('search')
|
||||
|
||||
eventBus.on({
|
||||
FOCUS_SEARCH_FIELD: () => {
|
||||
input.value?.focus()
|
||||
input.value?.select()
|
||||
}
|
||||
eventBus.on('FOCUS_SEARCH_FIELD', () => {
|
||||
input.value?.focus()
|
||||
input.value?.select()
|
||||
})
|
||||
</script>
|
||||
|
||||
|
|
|
@ -14,31 +14,22 @@ export const GlobalEventListeners = defineComponent({
|
|||
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()
|
||||
eventBus.on('PLAYLIST_DELETE', async 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')
|
||||
}
|
||||
}).on('PLAYLIST_FOLDER_DELETE', async folder => {
|
||||
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')
|
||||
}
|
||||
}).on('LOG_OUT', async () => {
|
||||
await userStore.logout()
|
||||
authService.destroy()
|
||||
forceReloadWindow()
|
||||
})
|
||||
|
||||
return () => slots.default?.()
|
||||
|
|
|
@ -103,9 +103,7 @@ export const useSongList = (songs: Ref<Song[]>, config: Partial<SongListConfig>
|
|||
songs.value = orderBy(songs.value, sortFields, order)
|
||||
}
|
||||
|
||||
eventBus.on('SONGS_DELETED', (deletedSongs: Song[]) => {
|
||||
songs.value = differenceBy(songs.value, deletedSongs, 'id')
|
||||
})
|
||||
eventBus.on('SONGS_DELETED', deletedSongs => (songs.value = differenceBy(songs.value, deletedSongs, 'id')))
|
||||
|
||||
provideReadonly(SongsKey, songs, false)
|
||||
provideReadonly(SelectedSongsKey, selectedSongs, false)
|
||||
|
|
|
@ -1,49 +1,52 @@
|
|||
export type EventName =
|
||||
| 'LOG_OUT'
|
||||
| 'TOGGLE_SIDEBAR'
|
||||
| 'SHOW_OVERLAY'
|
||||
| 'HIDE_OVERLAY'
|
||||
| 'FOCUS_SEARCH_FIELD'
|
||||
| 'PLAY_YOUTUBE_VIDEO'
|
||||
| 'INIT_EQUALIZER'
|
||||
| 'SEARCH_KEYWORDS_CHANGED'
|
||||
import { Ref } from 'vue'
|
||||
|
||||
| 'SONG_CONTEXT_MENU_REQUESTED'
|
||||
| 'ALBUM_CONTEXT_MENU_REQUESTED'
|
||||
| 'ARTIST_CONTEXT_MENU_REQUESTED'
|
||||
| 'CREATE_NEW_PLAYLIST_CONTEXT_MENU_REQUESTED'
|
||||
| 'PLAYLIST_CONTEXT_MENU_REQUESTED'
|
||||
| 'PLAYLIST_FOLDER_CONTEXT_MENU_REQUESTED'
|
||||
| 'CONTEXT_MENU_OPENED'
|
||||
export interface Events {
|
||||
LOG_OUT: () => void
|
||||
TOGGLE_SIDEBAR: () => void
|
||||
SHOW_OVERLAY: (options: Partial<OverlayState>) => void
|
||||
HIDE_OVERLAY: () => void
|
||||
FOCUS_SEARCH_FIELD: () => void
|
||||
PLAY_YOUTUBE_VIDEO: (payload: { id: string, title: string }) => void
|
||||
SEARCH_KEYWORDS_CHANGED: (keywords: string) => void
|
||||
|
||||
| 'MODAL_SHOW_ADD_USER_FORM'
|
||||
| 'MODAL_SHOW_EDIT_USER_FORM'
|
||||
| 'MODAL_SHOW_EDIT_SONG_FORM'
|
||||
| 'MODAL_SHOW_CREATE_PLAYLIST_FORM'
|
||||
| 'MODAL_SHOW_EDIT_PLAYLIST_FORM'
|
||||
| 'MODAL_SHOW_CREATE_SMART_PLAYLIST_FORM'
|
||||
| 'MODAL_SHOW_CREATE_PLAYLIST_FOLDER_FORM'
|
||||
| 'MODAL_SHOW_EDIT_PLAYLIST_FOLDER_FORM'
|
||||
| 'MODAL_SHOW_ABOUT_KOEL'
|
||||
| 'MODAL_SHOW_EQUALIZER'
|
||||
SONG_CONTEXT_MENU_REQUESTED: (event: MouseEvent, songs: Song | Song[]) => void
|
||||
ALBUM_CONTEXT_MENU_REQUESTED: (event: MouseEvent, album: Album) => void
|
||||
ARTIST_CONTEXT_MENU_REQUESTED: (event: MouseEvent, artist: Artist) => void
|
||||
CREATE_NEW_PLAYLIST_CONTEXT_MENU_REQUESTED: (event: MouseEvent) => void
|
||||
PLAYLIST_CONTEXT_MENU_REQUESTED: (event: MouseEvent, playlist: Playlist) => void
|
||||
PLAYLIST_FOLDER_CONTEXT_MENU_REQUESTED: (event: MouseEvent, playlistFolder: PlaylistFolder) => void
|
||||
CONTEXT_MENU_OPENED: (el: Ref<HTMLElement> | HTMLElement) => void
|
||||
|
||||
| 'PLAYLIST_DELETE'
|
||||
| 'PLAYLIST_FOLDER_DELETE'
|
||||
| 'PLAYLIST_SONGS_REMOVED'
|
||||
| 'PLAYLIST_UPDATED'
|
||||
| 'SONGS_UPDATED'
|
||||
| 'SONGS_DELETED'
|
||||
| 'SONG_QUEUED_FROM_ROUTE'
|
||||
MODAL_SHOW_ADD_USER_FORM: () => void
|
||||
MODAL_SHOW_EDIT_USER_FORM: (user: User) => void
|
||||
MODAL_SHOW_EDIT_SONG_FORM: (songs: Song | Song[], initialTab: EditSongFormTabName) => void
|
||||
MODAL_SHOW_CREATE_PLAYLIST_FORM: () => void
|
||||
MODAL_SHOW_EDIT_PLAYLIST_FORM: (playlist: Playlist) => void
|
||||
MODAL_SHOW_CREATE_SMART_PLAYLIST_FORM: () => void
|
||||
MODAL_SHOW_CREATE_PLAYLIST_FOLDER_FORM: () => void
|
||||
MODAL_SHOW_EDIT_PLAYLIST_FOLDER_FORM: (playlistFolder: PlaylistFolder) => void
|
||||
MODAL_SHOW_ABOUT_KOEL: () => void
|
||||
MODAL_SHOW_EQUALIZER: () => void
|
||||
|
||||
PLAYLIST_DELETE: (playlist: Playlist) => void
|
||||
PLAYLIST_FOLDER_DELETE: (playlistFolder: PlaylistFolder) => void
|
||||
PLAYLIST_SONGS_REMOVED: (playlist: Playlist, songs: Song[]) => void
|
||||
PLAYLIST_UPDATED: (playlist: Playlist) => void
|
||||
|
||||
SONGS_UPDATED: () => void
|
||||
SONGS_DELETED: (songs: Song[]) => void
|
||||
SONG_QUEUED_FROM_ROUTE: (songId: string) => void
|
||||
|
||||
SOCKET_TOGGLE_PLAYBACK: () => void
|
||||
SOCKET_TOGGLE_FAVORITE: () => void
|
||||
SOCKET_PLAY_NEXT: () => void
|
||||
SOCKET_PLAY_PREV: () => void
|
||||
SOCKET_PLAYBACK_STOPPED: () => void
|
||||
SOCKET_GET_STATUS: () => void
|
||||
SOCKET_STATUS: () => void
|
||||
SOCKET_GET_CURRENT_SONG: () => void
|
||||
SOCKET_SONG: (song: Song) => void
|
||||
SOCKET_SET_VOLUME: (volume: number) => void
|
||||
SOCKET_VOLUME_CHANGED: (volume: number) => void
|
||||
}
|
||||
|
||||
// socket events
|
||||
| 'SOCKET_TOGGLE_PLAYBACK'
|
||||
| 'SOCKET_TOGGLE_FAVORITE'
|
||||
| 'SOCKET_PLAY_NEXT'
|
||||
| 'SOCKET_PLAY_PREV'
|
||||
| 'SOCKET_PLAYBACK_STOPPED'
|
||||
| 'SOCKET_GET_STATUS'
|
||||
| 'SOCKET_STATUS'
|
||||
| 'SOCKET_GET_CURRENT_SONG'
|
||||
| 'SOCKET_SONG'
|
||||
| 'SOCKET_SET_VOLUME'
|
||||
| 'SOCKET_VOLUME_CHANGED'
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { expect, it, vi } from 'vitest'
|
||||
import { eventBus } from './eventBus'
|
||||
|
||||
new class extends UnitTestCase {
|
||||
protected beforeEach () {
|
||||
super.beforeEach(() => (eventBus.all = new Map()))
|
||||
}
|
||||
|
||||
protected test () {
|
||||
it('listens on a single event', () => {
|
||||
const mock = vi.fn()
|
||||
eventBus.on('SHOW_OVERLAY', mock)
|
||||
|
||||
eventBus.emit('SHOW_OVERLAY')
|
||||
|
||||
expect(mock).toHaveBeenCalledOnce()
|
||||
})
|
||||
|
||||
it('listens with parameters', () => {
|
||||
const mock = vi.fn()
|
||||
eventBus.on('SHOW_OVERLAY', mock)
|
||||
|
||||
eventBus.emit('SHOW_OVERLAY', 'foo', 'bar')
|
||||
|
||||
expect(mock).toHaveBeenNthCalledWith(1, 'foo', 'bar')
|
||||
})
|
||||
|
||||
it('registers multiple listeners at once', () => {
|
||||
const mock1 = vi.fn()
|
||||
const mock2 = vi.fn()
|
||||
|
||||
eventBus.on({
|
||||
SHOW_OVERLAY: mock1,
|
||||
MODAL_SHOW_ABOUT_KOEL: mock2
|
||||
})
|
||||
|
||||
eventBus.emit('SHOW_OVERLAY')
|
||||
expect(mock1).toHaveBeenCalledOnce()
|
||||
|
||||
eventBus.emit('MODAL_SHOW_ABOUT_KOEL')
|
||||
expect(mock2).toHaveBeenCalledOnce()
|
||||
})
|
||||
|
||||
it('queue up listeners on same event', () => {
|
||||
const mock1 = vi.fn()
|
||||
const mock2 = vi.fn()
|
||||
eventBus.on('SHOW_OVERLAY', mock1)
|
||||
eventBus.on('SHOW_OVERLAY', mock2)
|
||||
|
||||
eventBus.emit('SHOW_OVERLAY')
|
||||
|
||||
expect(mock1).toHaveBeenCalledOnce()
|
||||
expect(mock2).toHaveBeenCalledOnce()
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,30 +1,7 @@
|
|||
import { EventName } from '@/config'
|
||||
import { logger } from '@/utils'
|
||||
import { TypedEmitter } from 'tiny-typed-emitter'
|
||||
import { Events } from '@/config'
|
||||
|
||||
export const eventBus = {
|
||||
all: new Map(),
|
||||
const eventBus = new TypedEmitter<Events>()
|
||||
eventBus.setMaxListeners(100)
|
||||
|
||||
on (name: EventName | EventName[] | Partial<{ [K in EventName]: Closure }>, callback?: Closure) {
|
||||
if (Array.isArray(name)) {
|
||||
name.forEach(k => this.on(k, callback))
|
||||
return
|
||||
}
|
||||
|
||||
if (typeof name === 'object') {
|
||||
for (const k in name) {
|
||||
this.on(k as EventName, name[k as EventName])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
this.all.has(name) ? this.all.get(name).push(callback) : this.all.set(name, [callback])
|
||||
},
|
||||
|
||||
emit (name: EventName, ...args: any[]) {
|
||||
if (this.all.has(name)) {
|
||||
this.all.get(name).forEach((cb: Closure) => cb(...args))
|
||||
} else {
|
||||
logger.warn(`Event ${name} is not listened by any component`)
|
||||
}
|
||||
}
|
||||
}
|
||||
export { eventBus }
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
export * from './eventBus'
|
||||
export * from './formatters'
|
||||
export * from './supports'
|
||||
export * from './common'
|
||||
|
@ -8,3 +7,4 @@ export * from './fileReader'
|
|||
export * from './directoryReader'
|
||||
export * from './logger'
|
||||
export * from './floatingUi'
|
||||
export * from './eventBus'
|
||||
|
|
|
@ -6030,6 +6030,11 @@ through@2, through@^2.3.8, through@~2.3, through@~2.3.1:
|
|||
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
|
||||
integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==
|
||||
|
||||
tiny-typed-emitter@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz#b3b027fdd389ff81a152c8e847ee2f5be9fad7b5"
|
||||
integrity sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA==
|
||||
|
||||
tinybench@^2.2.1:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.3.0.tgz#febb2e697c735c0cdb8eb1e43cb1d2fa1821f983"
|
||||
|
|
Loading…
Reference in a new issue