migrated to vue wtf

This commit is contained in:
Daniel Ledda
2023-02-26 22:14:43 +01:00
parent b16e20a86a
commit 766faf5f56
54 changed files with 3135 additions and 3538 deletions

View File

@@ -1,136 +1,114 @@
import Beat, { BeatEvents } from "@/Beat";
import { Capsule, ICapsule, ISubscriber } from "@djledda/ladder";
import { type Beat, createBeat, deserialise as deserialiseBeat } from "@/Beat";
import { inject, computed, type InjectionKey, ref, shallowRef, triggerRef, watch } from "vue";
const EventTypeSubscriptions = [
BeatEvents.TimeSigUpChanged,
BeatEvents.BarCountChanged,
BeatEvents.GlobalDisplayTypeChanged,
BeatEvents.TrackListChanged,
BeatEvents.LockingChanged,
BeatEvents.AutoBeatSettingsChanged,
BeatEvents.DeepChange,
] as const;
type EventTypeSubscriptions = typeof EventTypeSubscriptions[number];
function defaultMainBeatGroup(): Beat {
const defaultSettings = {
barCount: 2,
isLooping: false,
timeSigUp: 8,
};
const mainBeatGroup = createBeat(defaultSettings);
mainBeatGroup.addTrack({ name: "LF" });
mainBeatGroup.addTrack({ name: "LH" });
mainBeatGroup.addTrack({ name: "RH" });
mainBeatGroup.addTrack({ name: "RF" });
return mainBeatGroup;
}
export default class BeatStore implements ISubscriber<EventTypeSubscriptions> {
private readonly beats: Beat[];
private activeBeat: ICapsule<Beat>;
private onBeatChangeCbs: (() => void)[] = [];
private autoSave: boolean;
private orientation: "horizontal" | "vertical" | null = null;
export function createBeatStore() {
const beats = shallowRef<Beat[]>([ defaultMainBeatGroup() ]);
const activeBeatIndex = ref(0);
const activeBeat = computed<Beat | null>(() => beats.value[activeBeatIndex.value] ?? null);
const autoSave = ref(true);
const orientation = ref<'horizontal' | 'vertical' | null>(null);
constructor(options: { loadFromLocalStorage: boolean, autoSave: boolean }) {
this.autoSave = options.autoSave;
if (options.loadFromLocalStorage) {
const save = localStorage.getItem("drum-slayer-save");
if (save) {
const serial = JSON.parse(save);
this.beats = [BeatStore.defaultMainBeatGroup()];
this.activeBeat = Capsule.new(this.beats[0]);
this.loadFromSave(serial);
if (this.autoSave) {
this.activeBeat.watch(() => this.save("localStorage"), true);
this.beats.forEach(beat => beat.addSubscriber(this, EventTypeSubscriptions));
}
return;
}
function resetActiveBeat(): void {
const current = activeBeat.value;
beats.value[activeBeatIndex.value] = defaultMainBeatGroup();
current?.destroy();
triggerRef(beats);
}
function removeBeat(index: number): void {
const beat = beats.value[index];
beats.value.splice(index, 1);
beat?.destroy();
triggerRef(beats);
}
function addNewBeat(): void {
const newBeat = defaultMainBeatGroup();
beats.value.push(newBeat);
if (autoSave.value) {
save("localStorage");
}
this.beats = [
BeatStore.defaultMainBeatGroup(),
];
this.activeBeat = Capsule.new(this.beats[0]);
triggerRef(beats);
}
notify(publisher: unknown, event: EventTypeSubscriptions): void {
this.save("localStorage");
}
static defaultMainBeatGroup(): Beat {
const defaultSettings = {
barCount: 2,
isLooping: false,
timeSigUp: 8,
};
const mainBeatGroup = new Beat(defaultSettings);
mainBeatGroup.addTrack({ name: "LF" });
mainBeatGroup.addTrack({ name: "LH" });
mainBeatGroup.addTrack({ name: "RH" });
mainBeatGroup.addTrack({ name: "RF" });
return mainBeatGroup;
}
getActiveBeat(): ICapsule<Beat> {
return this.activeBeat;
}
resetActiveBeat(): void {
const index = this.beats.indexOf(this.activeBeat.val);
const reset = BeatStore.defaultMainBeatGroup();
this.beats[index] = reset;
this.activeBeat.val = reset;
}
getBeats(): Beat[] {
return this.beats.slice();
}
setActiveBeat(beat: Beat): void {
const index = this.beats.indexOf(beat);
if (index !== -1) {
this.activeBeat.val = this.beats[index];
}
}
addNewBeat(): void {
const newBeat = BeatStore.defaultMainBeatGroup();
this.beats.push(newBeat);
if (this.autoSave) {
newBeat.addSubscriber(this, EventTypeSubscriptions);
}
this.onBeatChangeCbs.forEach(cb => cb());
if (this.autoSave) {
this.save("localStorage");
}
}
onBeatChanges(callback: () => void) {
this.onBeatChangeCbs.push(callback);
}
save(destination: "localStorage"): void {
function save(destination: "localStorage"): void {
if (destination === "localStorage") {
const serials = this.beats.map(beat => beat.serialise());
const serials = beats.value.map(beat => beat.serialise());
localStorage.setItem("drum-slayer-save", JSON.stringify({
beats: serials,
activeBeatIndex: this.beats.indexOf(this.activeBeat.val),
orientation: this.orientation,
activeBeatIndex: activeBeatIndex.value,
orientation: orientation.value,
}));
}
}
loadFromSave(source: any): void {
this.beats.length = 0;
function loadFromSave(source: any): void {
beats.value.length = 0;
if (Array.isArray(source.beats)
&& (typeof source.activeBeatIndex === "number" || typeof source.activeBeatIndex === "undefined")
&& typeof source.orientation === "string") {
try {
source.beats.forEach((beat: any) => this.beats.push(Beat.deserialise(beat)));
source.beats.forEach((beat: any) => beats.value.push(deserialiseBeat(beat)));
if (typeof source.activeBeatIndex === "number") {
this.activeBeat.val = this.beats[source.activeBeatIndex];
activeBeatIndex.value = source.activeBeatIndex;
}
this.orientation = source.orientation;
orientation.value = source.orientation;
} catch (err) {
console.error(err);
}
} else {
resetActiveBeat();
}
}
setOrientation(orientation: "horizontal" | "vertical"): void {
this.orientation = orientation;
this.save("localStorage");
function bakeAll(): void {
activeBeat.value?.bakeLoops();
}
getSavedOrientation(): "horizontal" | "vertical" | null {
return this.orientation;
watch([activeBeatIndex, orientation, beats], () => {
save('localStorage');
});
const savedItem = localStorage.getItem('drum-slayer-save');
if (savedItem) {
const serial = JSON.parse(savedItem);
beats.value = [defaultMainBeatGroup()];
loadFromSave(serial);
}
}
return {
beats,
activeBeatIndex,
activeBeat,
autoSave,
orientation,
save,
addNewBeat,
removeBeat,
resetActiveBeat,
bakeAll,
};
}
export type BeatStore = ReturnType<typeof createBeatStore>;
export const BeatStoreKey = Symbol('BeatStore') as InjectionKey<BeatStore>;
export function useBeatStore(): BeatStore {
return inject(BeatStoreKey, createBeatStore, true);
}