mirror of
https://github.com/Myxelium/Bridge-Multi.git
synced 2026-04-11 14:19:38 +00:00
Refactor search service
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
<app-search-bar (resultsUpdated)="onResultsUpdated($event)"></app-search-bar>
|
<app-search-bar></app-search-bar>
|
||||||
<div class="ui celled two column grid">
|
<div class="ui celled two column grid">
|
||||||
<div id="table-row" class="row">
|
<div id="table-row" class="row">
|
||||||
<div id="table-column" class="column twelve wide">
|
<div id="table-column" class="column twelve wide">
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { Component, ViewChild, AfterViewInit } from '@angular/core'
|
import { Component, ViewChild, AfterViewInit } from '@angular/core'
|
||||||
import { ChartSidebarComponent } from './chart-sidebar/chart-sidebar.component'
|
import { ChartSidebarComponent } from './chart-sidebar/chart-sidebar.component'
|
||||||
import { StatusBarComponent } from './status-bar/status-bar.component'
|
import { StatusBarComponent } from './status-bar/status-bar.component'
|
||||||
import { SongResult } from 'src/electron/shared/interfaces/search.interface'
|
|
||||||
import { ResultTableComponent } from './result-table/result-table.component'
|
import { ResultTableComponent } from './result-table/result-table.component'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -35,15 +34,6 @@ export class BrowseComponent implements AfterViewInit {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
onResultsUpdated(results: SongResult[]) {
|
|
||||||
this.resultTable.results = results
|
|
||||||
this.resultTable.onNewSearch()
|
|
||||||
this.resultTable.checkAll(false)
|
|
||||||
this.chartSidebar.selectVersion(undefined)
|
|
||||||
this.statusBar.resultCount = results.length
|
|
||||||
this.statusBar.selectedResults = []
|
|
||||||
}
|
|
||||||
|
|
||||||
loadMoreResults() {
|
loadMoreResults() {
|
||||||
// TODO: use the same query as the current search, but append more results if there are any more to be viewed
|
// TODO: use the same query as the current search, but append more results if there are any more to be viewed
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,35 @@
|
|||||||
import { Component } from '@angular/core'
|
import { Component, OnInit } from '@angular/core'
|
||||||
import { SongResult } from '../../../../electron/shared/interfaces/search.interface'
|
import { SongResult } from '../../../../electron/shared/interfaces/search.interface'
|
||||||
import { ElectronService } from '../../../core/services/electron.service'
|
import { ElectronService } from '../../../core/services/electron.service'
|
||||||
import { VersionResult } from '../../../../electron/shared/interfaces/songDetails.interface'
|
import { VersionResult } from '../../../../electron/shared/interfaces/songDetails.interface'
|
||||||
import { AlbumArtService } from '../../../core/services/album-art.service'
|
import { AlbumArtService } from '../../../core/services/album-art.service'
|
||||||
import { DownloadService } from '../../../core/services/download.service'
|
import { DownloadService } from '../../../core/services/download.service'
|
||||||
import { groupBy } from 'src/electron/shared/UtilFunctions'
|
import { groupBy } from 'src/electron/shared/UtilFunctions'
|
||||||
|
import { SearchService } from 'src/app/core/services/search.service'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-chart-sidebar',
|
selector: 'app-chart-sidebar',
|
||||||
templateUrl: './chart-sidebar.component.html',
|
templateUrl: './chart-sidebar.component.html',
|
||||||
styleUrls: ['./chart-sidebar.component.scss']
|
styleUrls: ['./chart-sidebar.component.scss']
|
||||||
})
|
})
|
||||||
export class ChartSidebarComponent {
|
export class ChartSidebarComponent implements OnInit {
|
||||||
|
|
||||||
private songResult: SongResult
|
private songResult: SongResult
|
||||||
selectedVersion: VersionResult
|
selectedVersion: VersionResult
|
||||||
charts: VersionResult[][]
|
charts: VersionResult[][]
|
||||||
|
|
||||||
constructor(private electronService: ElectronService, private albumArtService: AlbumArtService, private downloadService: DownloadService) { }
|
constructor(
|
||||||
|
private electronService: ElectronService,
|
||||||
|
private albumArtService: AlbumArtService,
|
||||||
|
private downloadService: DownloadService,
|
||||||
|
private searchService: SearchService
|
||||||
|
) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.searchService.onNewSearch(() => {
|
||||||
|
this.selectVersion(undefined)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays the information for the selected song.
|
* Displays the information for the selected song.
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import { Component, Input, Output, EventEmitter, ViewChildren, QueryList, ViewChild } from '@angular/core'
|
import { Component, Output, EventEmitter, ViewChildren, QueryList, ViewChild, OnInit } from '@angular/core'
|
||||||
import { SongResult } from '../../../../electron/shared/interfaces/search.interface'
|
import { SongResult } from '../../../../electron/shared/interfaces/search.interface'
|
||||||
import { ResultTableRowComponent } from './result-table-row/result-table-row.component'
|
import { ResultTableRowComponent } from './result-table-row/result-table-row.component'
|
||||||
import { CheckboxDirective } from 'src/app/core/directives/checkbox.directive'
|
import { CheckboxDirective } from 'src/app/core/directives/checkbox.directive'
|
||||||
|
import { SearchService } from 'src/app/core/services/search.service'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-result-table',
|
selector: 'app-result-table',
|
||||||
templateUrl: './result-table.component.html',
|
templateUrl: './result-table.component.html',
|
||||||
styleUrls: ['./result-table.component.scss']
|
styleUrls: ['./result-table.component.scss']
|
||||||
})
|
})
|
||||||
export class ResultTableComponent {
|
export class ResultTableComponent implements OnInit {
|
||||||
@Input() results: SongResult[]
|
|
||||||
|
|
||||||
@Output() rowClicked = new EventEmitter<SongResult>()
|
@Output() rowClicked = new EventEmitter<SongResult>()
|
||||||
@Output() songChecked = new EventEmitter<SongResult>()
|
@Output() songChecked = new EventEmitter<SongResult>()
|
||||||
@@ -18,7 +18,23 @@ export class ResultTableComponent {
|
|||||||
@ViewChild(CheckboxDirective, { static: true }) checkboxColumn: CheckboxDirective
|
@ViewChild(CheckboxDirective, { static: true }) checkboxColumn: CheckboxDirective
|
||||||
@ViewChildren('tableRow') tableRows: QueryList<ResultTableRowComponent>
|
@ViewChildren('tableRow') tableRows: QueryList<ResultTableRowComponent>
|
||||||
|
|
||||||
constructor() { }
|
results: SongResult[]
|
||||||
|
|
||||||
|
constructor(private searchService: SearchService) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.searchService.onNewSearch(() => {
|
||||||
|
this.checkboxColumn.check(false)
|
||||||
|
this.checkAll(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
this.searchService.onSearchChanged(results => {
|
||||||
|
this.results = results
|
||||||
|
if (this.checkboxColumn.isChecked) {
|
||||||
|
this.checkAll(true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
onRowClicked(result: SongResult) {
|
onRowClicked(result: SongResult) {
|
||||||
this.rowClicked.emit(result)
|
this.rowClicked.emit(result)
|
||||||
@@ -39,8 +55,4 @@ export class ResultTableComponent {
|
|||||||
onSongsDeselected(songs: SongResult['id'][]) {
|
onSongsDeselected(songs: SongResult['id'][]) {
|
||||||
this.tableRows.forEach(row => row.check(!songs.includes(row.songID)))
|
this.tableRows.forEach(row => row.check(!songs.includes(row.songID)))
|
||||||
}
|
}
|
||||||
|
|
||||||
onNewSearch() {
|
|
||||||
this.checkboxColumn.check(false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
<a class="item">Charter</a>
|
<a class="item">Charter</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="item right">
|
<!-- TODO <div class="item right">
|
||||||
<button class="ui positive disabled button">Bulk Download</button>
|
<button class="ui positive disabled button">Bulk Download</button>
|
||||||
</div> -->
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Component, AfterViewInit, Output, EventEmitter } from '@angular/core'
|
import { Component, AfterViewInit } from '@angular/core'
|
||||||
import { ElectronService } from '../../../core/services/electron.service'
|
import { SearchService } from 'src/app/core/services/search.service'
|
||||||
import { SearchType, SongResult } from '../../../../electron/shared/interfaces/search.interface'
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-search-bar',
|
selector: 'app-search-bar',
|
||||||
@@ -8,17 +7,14 @@ import { SearchType, SongResult } from '../../../../electron/shared/interfaces/s
|
|||||||
styleUrls: ['./search-bar.component.scss']
|
styleUrls: ['./search-bar.component.scss']
|
||||||
})
|
})
|
||||||
export class SearchBarComponent implements AfterViewInit {
|
export class SearchBarComponent implements AfterViewInit {
|
||||||
@Output() resultsUpdated = new EventEmitter<SongResult[]>()
|
|
||||||
|
|
||||||
constructor(private electronService: ElectronService) { }
|
constructor(private searchService: SearchService) { }
|
||||||
|
|
||||||
ngAfterViewInit() {
|
ngAfterViewInit() {
|
||||||
$('.ui.dropdown').dropdown()
|
$('.ui.dropdown').dropdown()
|
||||||
}
|
}
|
||||||
|
|
||||||
async onSearch(query: string) {
|
async onSearch(query: string) {
|
||||||
const results = await this.electronService.invoke('song-search', { query, type: SearchType.Any })
|
this.searchService.newSearch(query)
|
||||||
|
|
||||||
this.resultsUpdated.emit(results)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,7 @@ import { DownloadService } from 'src/app/core/services/download.service'
|
|||||||
import { ElectronService } from 'src/app/core/services/electron.service'
|
import { ElectronService } from 'src/app/core/services/electron.service'
|
||||||
import { groupBy } from 'src/electron/shared/UtilFunctions'
|
import { groupBy } from 'src/electron/shared/UtilFunctions'
|
||||||
import { VersionResult } from 'src/electron/shared/interfaces/songDetails.interface'
|
import { VersionResult } from 'src/electron/shared/interfaces/songDetails.interface'
|
||||||
|
import { SearchService } from 'src/app/core/services/search.service'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-status-bar',
|
selector: 'app-status-bar',
|
||||||
@@ -21,12 +22,25 @@ export class StatusBarComponent {
|
|||||||
batchResults: VersionResult[]
|
batchResults: VersionResult[]
|
||||||
chartGroups: VersionResult[][]
|
chartGroups: VersionResult[][]
|
||||||
|
|
||||||
constructor(private electronService: ElectronService, private downloadService: DownloadService, ref: ChangeDetectorRef) {
|
constructor(
|
||||||
|
private electronService: ElectronService,
|
||||||
|
private downloadService: DownloadService,
|
||||||
|
searchService: SearchService,
|
||||||
|
ref: ChangeDetectorRef
|
||||||
|
) {
|
||||||
downloadService.onDownloadUpdated(() => {
|
downloadService.onDownloadUpdated(() => {
|
||||||
this.downloading = downloadService.downloadCount > 0
|
this.downloading = downloadService.downloadCount > 0
|
||||||
this.percent = downloadService.totalPercent
|
this.percent = downloadService.totalPercent
|
||||||
ref.detectChanges()
|
ref.detectChanges()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
searchService.onSearchChanged(() => {
|
||||||
|
this.resultCount = searchService.resultCount
|
||||||
|
})
|
||||||
|
|
||||||
|
searchService.onNewSearch(() => {
|
||||||
|
this.selectedResults = []
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
showDownloads() {
|
showDownloads() {
|
||||||
@@ -60,11 +74,11 @@ export class StatusBarComponent {
|
|||||||
const downloadSong = this.selectedResults.find(song => song.id == downloadVersion.songID)
|
const downloadSong = this.selectedResults.find(song => song.id == downloadVersion.songID)
|
||||||
this.downloadService.addDownload(
|
this.downloadService.addDownload(
|
||||||
downloadVersion.versionID, {
|
downloadVersion.versionID, {
|
||||||
avTagName: downloadVersion.avTagName,
|
avTagName: downloadVersion.avTagName,
|
||||||
artist: downloadSong.artist,
|
artist: downloadSong.artist,
|
||||||
charter: downloadVersion.charters,
|
charter: downloadVersion.charters,
|
||||||
links: JSON.parse(downloadVersion.downloadLink)
|
links: JSON.parse(downloadVersion.downloadLink)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$('#selectedModal').modal('show')
|
$('#selectedModal').modal('show')
|
||||||
@@ -78,11 +92,11 @@ export class StatusBarComponent {
|
|||||||
const downloadSong = this.selectedResults.find(song => song.id == version.songID)
|
const downloadSong = this.selectedResults.find(song => song.id == version.songID)
|
||||||
this.downloadService.addDownload(
|
this.downloadService.addDownload(
|
||||||
version.versionID, {
|
version.versionID, {
|
||||||
avTagName: version.avTagName,
|
avTagName: version.avTagName,
|
||||||
artist: downloadSong.artist,
|
artist: downloadSong.artist,
|
||||||
charter: version.charters,
|
charter: version.charters,
|
||||||
links: JSON.parse(version.downloadLink)
|
links: JSON.parse(version.downloadLink)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,24 +6,33 @@ import { Directive, ElementRef, Output, EventEmitter, AfterViewInit } from '@ang
|
|||||||
export class CheckboxDirective implements AfterViewInit {
|
export class CheckboxDirective implements AfterViewInit {
|
||||||
@Output() checked = new EventEmitter<boolean>()
|
@Output() checked = new EventEmitter<boolean>()
|
||||||
|
|
||||||
|
_isChecked = false
|
||||||
|
|
||||||
constructor(private checkbox: ElementRef) { }
|
constructor(private checkbox: ElementRef) { }
|
||||||
|
|
||||||
ngAfterViewInit() {
|
ngAfterViewInit() {
|
||||||
$(this.checkbox.nativeElement).checkbox({
|
$(this.checkbox.nativeElement).checkbox({
|
||||||
onChecked: () => {
|
onChecked: () => {
|
||||||
this.checked.emit(true)
|
this.checked.emit(true)
|
||||||
|
this._isChecked = true
|
||||||
},
|
},
|
||||||
onUnchecked: () => {
|
onUnchecked: () => {
|
||||||
this.checked.emit(false)
|
this.checked.emit(false)
|
||||||
|
this._isChecked = false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
check(isChecked: boolean) {
|
check(isChecked: boolean) {
|
||||||
|
this._isChecked = isChecked
|
||||||
if (isChecked) {
|
if (isChecked) {
|
||||||
$(this.checkbox.nativeElement).checkbox('check')
|
$(this.checkbox.nativeElement).checkbox('check')
|
||||||
} else {
|
} else {
|
||||||
$(this.checkbox.nativeElement).checkbox('uncheck')
|
$(this.checkbox.nativeElement).checkbox('uncheck')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get isChecked() {
|
||||||
|
return this._isChecked
|
||||||
|
}
|
||||||
}
|
}
|
||||||
33
src/app/core/services/search.service.ts
Normal file
33
src/app/core/services/search.service.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import { Injectable, EventEmitter } from '@angular/core'
|
||||||
|
import { ElectronService } from './electron.service'
|
||||||
|
import { SearchType, SongResult } from 'src/electron/shared/interfaces/search.interface'
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class SearchService {
|
||||||
|
|
||||||
|
private resultsChangedEmitter = new EventEmitter<SongResult[]>() // For when any results change
|
||||||
|
private newResultsEmitter = new EventEmitter<SongResult[]>() // For when a new search happens
|
||||||
|
private results: SongResult[] = []
|
||||||
|
|
||||||
|
constructor(private electronService: ElectronService) { }
|
||||||
|
|
||||||
|
async newSearch(query: string) {
|
||||||
|
this.results = await this.electronService.invoke('song-search', { query, type: SearchType.Any })
|
||||||
|
this.newResultsEmitter.emit(this.results)
|
||||||
|
this.resultsChangedEmitter.emit(this.results)
|
||||||
|
}
|
||||||
|
|
||||||
|
onSearchChanged(callback: (results: SongResult[]) => void) {
|
||||||
|
this.resultsChangedEmitter.subscribe(callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
onNewSearch(callback: (results: SongResult[]) => void) {
|
||||||
|
this.newResultsEmitter.subscribe(callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
get resultCount() {
|
||||||
|
return this.results.length
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user