Files
Lazuli/src/lib/stores.ts

129 lines
4.2 KiB
TypeScript
Raw Normal View History

import { writable, readable, readonly, type Writable, type Readable } from 'svelte/store'
2024-01-25 03:05:13 -05:00
import type { AlertType } from '$lib/components/util/alert.svelte'
2024-01-27 01:38:04 -05:00
export const pageWidth: Writable<number> = writable()
2024-01-27 01:38:04 -05:00
export const newestAlert: Writable<[AlertType, string]> = writable()
const youtubeMusicBackground: string = 'https://www.gstatic.com/youtube/media/ytm/images/sbg/wsbg@4000x2250.png' // Default Youtube music background
export const backgroundImage: Writable<string> = writable(youtubeMusicBackground)
2024-04-16 10:05:11 -04:00
export const itemDisplayState: Writable<'list' | 'grid'> = writable('grid')
function fisherYatesShuffle<T>(items: T[]) {
for (let currentIndex = items.length - 1; currentIndex >= 0; currentIndex--) {
let randomIndex = Math.floor(Math.random() * (currentIndex + 1))
;[items[currentIndex], items[randomIndex]] = [items[randomIndex], items[currentIndex]]
}
return items
}
2024-04-16 10:05:11 -04:00
class Queue {
private currentPosition: number // -1 means no song is playing
private originalSongs: Song[]
private currentSongs: Song[]
private shuffled: boolean
2024-04-16 10:05:11 -04:00
constructor() {
2024-04-22 14:18:42 -04:00
this.currentPosition = -1
this.originalSongs = []
this.currentSongs = []
this.shuffled = false
2024-04-16 10:05:11 -04:00
}
private updateQueue() {
writableQueue.set(this)
// TODO: Implement Queue Saver
}
2024-04-22 14:18:42 -04:00
get current() {
if (this.currentSongs.length === 0) return null
2024-05-16 21:45:39 -04:00
if (this.currentPosition === -1) this.currentPosition = 0
return this.currentSongs[this.currentPosition]
2024-04-16 10:05:11 -04:00
}
2024-04-22 14:18:42 -04:00
get list() {
return this.currentSongs
}
get isShuffled() {
return this.shuffled
}
/** Sets the currently playing song to the song provided as long as it is in the current playlist */
public setCurrent(newSong: Song) {
const queuePosition = this.currentSongs.findIndex((song) => song === newSong)
if (queuePosition < 0) return
this.currentPosition = queuePosition
this.updateQueue()
}
/** Shuffles all songs in the queue after the currently playing song */
public shuffle() {
const shuffledSongs = fisherYatesShuffle(this.currentSongs.slice(this.currentPosition + 1))
this.currentSongs = this.currentSongs.slice(0, this.currentPosition + 1).concat(shuffledSongs)
this.shuffled = true
this.updateQueue()
}
/** Restores the queue to its original ordered state, while maintaining whatever song is currently playing */
public reorder() {
const originalPosition = this.originalSongs.findIndex((song) => song === this.currentSongs[this.currentPosition])
this.currentSongs = [...this.originalSongs]
this.currentPosition = originalPosition
this.shuffled = false
this.updateQueue()
2024-04-16 10:05:11 -04:00
}
/** Starts the next song */
2024-04-22 14:18:42 -04:00
public next() {
if (this.currentSongs.length === 0 || this.currentSongs.length <= this.currentPosition + 1) return
2024-04-22 14:18:42 -04:00
this.currentPosition += 1
this.updateQueue()
}
2024-04-16 10:05:11 -04:00
/** Plays the previous song */
2024-04-22 14:18:42 -04:00
public previous() {
if (this.currentSongs.length === 0 || this.currentPosition <= 0) return
2024-04-22 14:18:42 -04:00
this.currentPosition -= 1
this.updateQueue()
2024-04-22 14:18:42 -04:00
}
/** Add songs to the end of the queue */
2024-04-22 14:18:42 -04:00
public enqueue(...songs: Song[]) {
this.originalSongs.push(...songs)
this.currentSongs.push(...songs)
this.updateQueue()
2024-04-22 14:18:42 -04:00
}
/**
* @param songs An ordered array of Songs
* @param shuffled Whether or not to shuffle the queue before starting playback. False if not specified
*/
public setQueue(songs: Song[], shuffled?: boolean) {
if (songs.length === 0) return // Should not set a queue with no songs, use clear()
this.originalSongs = songs
this.currentSongs = shuffled ? fisherYatesShuffle(songs) : songs
this.currentPosition = 0
this.shuffled = shuffled ?? false
this.updateQueue()
}
/** Clears all items from the queue */
2024-04-22 14:18:42 -04:00
public clear() {
this.currentPosition = -1
this.originalSongs = []
this.currentSongs = []
this.updateQueue()
2024-04-16 10:05:11 -04:00
}
}
2024-04-22 14:18:42 -04:00
const writableQueue: Writable<Queue> = writable(new Queue())
export const queue: Readable<Queue> = readonly(writableQueue)