swingmusic/src/stores/queue.ts
geoffrey45 b497344521 refactor logo, bottom bar and perks.js
- add new logo
- add tsconfig.json
- move logo to new component
- update bottombar
- remove props from hotkeys and progress bar
- convert perks.js -> perks.ts
2022-05-24 15:55:26 +03:00

242 lines
6.0 KiB
TypeScript

import { defineStore } from "pinia";
import state from "../composables/state";
import { useNotifStore, NotifType } from "./notification";
import {
Track,
fromFolder,
fromAlbum,
fromPlaylist,
fromSearch,
} from "../interfaces";
import notif from "../composables/mediaNotification";
import { FromOptions } from "../composables/enums";
function writeQueue(
from: fromFolder | fromAlbum | fromPlaylist,
tracks: Track[]
) {
localStorage.setItem(
"queue",
JSON.stringify({
from: from,
tracks: tracks,
})
);
}
function writeCurrent(track: Track) {
localStorage.setItem("current", JSON.stringify(track));
}
function readCurrent(): Track {
const current = localStorage.getItem("current");
if (current) {
return JSON.parse(current);
}
return defaultTrack;
}
const defaultTrack = <Track>{
title: "Nothing played yet",
artists: ["Alice"],
trackid: "",
image: "",
};
export default defineStore("Queue", {
state: () => ({
progressElem: HTMLElement,
audio: new Audio(),
track: {
current_time: 0,
duration: 0,
},
current: <Track>{},
length: 0,
next: <Track>{},
prev: <Track>{},
playing: false,
from: <fromFolder>{} || <fromAlbum>{} || <fromPlaylist>{},
tracks: <Track[]>[defaultTrack],
}),
actions: {
play(track: Track) {
const uri = state.settings.uri + "/file/" + track.trackid;
const elem = document.getElementById("progress");
this.updateCurrent(track);
new Promise((resolve, reject) => {
this.audio.src = uri;
this.audio.oncanplaythrough = resolve;
this.audio.onerror = reject;
})
.then(() => {
this.length = this.audio.duration;
this.audio.play().then(() => {
this.playing = true;
notif(track, this.playPause, this.playNext, this.playPrev);
this.audio.ontimeupdate = () => {
this.track.current_time = this.audio.currentTime;
const current_time =
(this.audio.currentTime / this.audio.duration) * 100;
elem.style.backgroundSize = `${this.current_time}% 100%`;
};
this.audio.onended = () => {
this.playNext();
};
});
})
.catch((err) => {
console.error(err);
});
},
playPause() {
if (this.audio.src === "") {
this.play(this.current);
} else if (this.audio.paused) {
this.audio.play();
this.playing = true;
} else {
this.audio.pause();
this.playing = false;
}
},
playNext() {
this.play(this.next);
},
playPrev() {
this.play(this.prev);
},
seek(pos: number) {
try {
const a = (pos / 100) * this.audio.duration;
this.audio.currentTime = a;
} catch (error) {
if (error instanceof TypeError) {
console.error("Seek error: no audio");
}
}
},
readQueue() {
const queue = localStorage.getItem("queue");
if (queue) {
const parsed = JSON.parse(queue);
this.from = parsed.from;
this.tracks = parsed.tracks;
}
this.updateCurrent(readCurrent());
},
updateCurrent(track: Track) {
this.current = track;
this.updateNext(this.current);
this.updatePrev(this.current);
writeCurrent(track);
},
updateNext(track: Track) {
const index = this.tracks.findIndex(
(t: Track) => t.trackid == track.trackid
);
if (index == this.tracks.length - 1) {
this.next = this.tracks[0];
} else if (index == 0) {
this.next = this.tracks[1];
} else {
this.next = this.tracks[index + 1];
}
},
updatePrev(track: Track) {
const index = this.tracks.findIndex(
(t: Track) => t.trackid === track.trackid
);
if (index === 0) {
this.prev = this.tracks[this.tracks.length - 1];
} else if (index === this.tracks.length - 1) {
this.prev = this.tracks[index - 1];
} else {
this.prev = this.tracks[index - 1];
}
},
setNewQueue(tracklist: Track[]) {
if (this.tracks !== tracklist) {
this.tracks = [];
this.tracks.push(...tracklist);
writeQueue(this.from, this.tracks);
}
},
playFromFolder(fpath: string, tracks: Track[]) {
this.from = <fromFolder>{
type: FromOptions.folder,
path: fpath,
name: fpath.split("/").splice(-1).join(""),
};
this.setNewQueue(tracks);
},
playFromAlbum(aname: string, albumartist: string, tracks: Track[]) {
this.from = <fromAlbum>{
type: FromOptions.album,
name: aname,
albumartist: albumartist,
};
this.setNewQueue(tracks);
},
playFromPlaylist(pname: string, pid: string, tracks: Track[]) {
this.from = <fromPlaylist>{
type: FromOptions.playlist,
name: pname,
playlistid: pid,
};
this.setNewQueue(tracks);
},
playFromSearch(query: string, tracks: Track[]) {
this.from = <fromSearch>{
type: FromOptions.search,
query: query,
};
this.setNewQueue(tracks);
},
addTrackToQueue(track: Track) {
this.tracks.push(track);
writeQueue(this.from, this.tracks);
this.updateNext(this.current);
},
playTrackNext(track: Track) {
const Toast = useNotifStore();
const currentid = this.tracks.findIndex(
(t: Track) => t.trackid === this.current.trackid
);
if (currentid == this.tracks.length - 1) {
this.tracks.push(track);
} else {
const next: Track = this.tracks[currentid + 1];
if (next.trackid === track.trackid) {
Toast.showNotification("Track is already queued", NotifType.Info);
return;
}
}
this.tracks.splice(currentid + 1, 0, track);
this.updateNext(this.current);
Toast.showNotification(
`Added ${track.title} to queue`,
NotifType.Success
);
writeQueue(this.from, this.tracks);
},
},
});