74 lines
2.1 KiB
TypeScript
74 lines
2.1 KiB
TypeScript
import {computed, effect, Signal, signal, WritableSignal} from '@angular/core';
|
|
|
|
export class IndexedArray<T> {
|
|
protected list: WritableSignal<T[]> = signal([]);
|
|
protected currentIndex: WritableSignal<number> = signal(0);
|
|
|
|
public playlist: Signal<T[]> = this.list.asReadonly();
|
|
public index: Signal<number> = this.currentIndex.asReadonly();
|
|
public current: Signal<T|null>;
|
|
|
|
constructor() {
|
|
this.current = computed(() : T | null => {
|
|
if (this.currentIndex() > -1 && this.list().length === 0) return null;
|
|
return this.list()[this.currentIndex()];
|
|
});
|
|
}
|
|
|
|
next(): T | null {
|
|
const length = this.list().length;
|
|
if (length === 0) return null;
|
|
if (length === 1) return this.list()[0];
|
|
|
|
if (this.currentIndex() === length - 1) {
|
|
this.currentIndex.set(0);
|
|
} else {
|
|
this.currentIndex.set(this.currentIndex() + 1);
|
|
}
|
|
|
|
return this.current();
|
|
}
|
|
|
|
prev(): T | null {
|
|
const length = this.list().length;
|
|
if (length === 0) return null;
|
|
if (length === 1) return this.list()[0];
|
|
|
|
if (this.currentIndex() === 0) {
|
|
this.currentIndex.set(length - 1);
|
|
} else {
|
|
this.currentIndex.set(this.currentIndex() - 1);
|
|
}
|
|
|
|
return this.current();
|
|
}
|
|
|
|
add(item: T) {
|
|
this.list.update((list: T[]) => {
|
|
return [...list, item];
|
|
});
|
|
}
|
|
|
|
remove(item: T) {
|
|
// Check item is actually in the list, and find its index
|
|
const index = this.list().indexOf(item);
|
|
if (index > -1) {
|
|
// If we deleted an item before the current index pointer, then shift the index back one to maintain current item
|
|
if (index < this.currentIndex()) {
|
|
this.currentIndex.update((index) => index - 1);
|
|
}
|
|
|
|
// If we are at the end of the list (and the list won't become empty) shift index back to maintain pointer at end of list
|
|
if (index === this.list().length - 1 && index > 0) {
|
|
this.currentIndex.update((index) => index - 1);
|
|
}
|
|
|
|
// Remove the item
|
|
this.list.update((list: T[]) => {
|
|
list.splice(index, 1);
|
|
return [...list];
|
|
});
|
|
}
|
|
}
|
|
}
|