import {computed, effect, Signal, signal, WritableSignal} from '@angular/core'; export class IndexedArray { protected list: WritableSignal = signal([]); protected currentIndex: WritableSignal = signal(0); public playlist: Signal = this.list.asReadonly(); public index: Signal = this.currentIndex.asReadonly(); public current: Signal; 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]; }); } } }