Refactor song selection to a service

This commit is contained in:
Geomitron
2020-05-10 19:53:53 -04:00
parent 8a4620d771
commit e41d69da46
8 changed files with 143 additions and 65 deletions

View File

@@ -0,0 +1,96 @@
import { Injectable, EventEmitter } from '@angular/core'
import { SongResult } from 'src/electron/shared/interfaces/search.interface'
import { SearchService } from './search.service'
// Note: this class prevents event cycles by only emitting events if the checkbox changes
@Injectable({
providedIn: 'root'
})
export class SelectionService {
private searchResults: SongResult[] = []
private selectAllChangedEmitter = new EventEmitter<boolean>()
private selectionChangedEmitters: { [songID: number]: EventEmitter<boolean> } = {}
private allSelected = false
private selections: { [songID: number]: boolean | undefined } = {}
constructor(searchService: SearchService) {
searchService.onSearchChanged((results) => {
this.searchResults = results
this.removeOldListeners(results.map(result => result.id))
if (this.allSelected) {
this.selectAll() // Select newly added rows if allSelected
}
})
searchService.onNewSearch((results) => {
this.searchResults = results
this.removeOldListeners(results.map(result => result.id))
this.deselectAll()
})
}
private removeOldListeners(songIDs: number[]) {
for (const oldSongID in this.selectionChangedEmitters) {
if (!songIDs.find(newSongID => newSongID == Number(oldSongID))) {
delete this.selectionChangedEmitters[oldSongID]
delete this.selections[oldSongID]
}
}
}
getSelectedResults() {
return this.searchResults.filter(result => this.selections[result.id] == true)
}
onSelectAllChanged(callback: (selected: boolean) => void) {
this.selectAllChangedEmitter.subscribe(callback)
}
/**
* Emits an event when the selection for `songID` needs to change.
* (note: only one emitter can be registered per `songID`)
*/
onSelectionChanged(songID: number, callback: (selection: boolean) => void) {
this.selectionChangedEmitters[songID] = new EventEmitter()
this.selectionChangedEmitters[songID].subscribe(callback)
}
deselectAll() {
if (this.allSelected) {
this.allSelected = false
this.selectAllChangedEmitter.emit(false)
}
setTimeout(() => this.searchResults.forEach(result => this.deselectSong(result.id)), 0)
}
selectAll() {
if (!this.allSelected) {
this.allSelected = true
this.selectAllChangedEmitter.emit(true)
}
setTimeout(() => this.searchResults.forEach(result => this.selectSong(result.id)), 0)
}
deselectSong(songID: number) {
if (this.selections[songID]) {
this.selections[songID] = false
this.selectionChangedEmitters[songID].emit(false)
}
}
selectSong(songID: number) {
if (!this.selections[songID] && this.selectionChangedEmitters[songID] != undefined) {
this.selections[songID] = true
this.selectionChangedEmitters[songID].emit(true)
}
}
}