mirror of
https://github.com/Myxelium/Bridge-Multi.git
synced 2026-04-11 14:19:38 +00:00
Added scroll to show more results
This commit is contained in:
@@ -2,6 +2,7 @@ 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 { ResultTableComponent } from './result-table/result-table.component'
|
import { ResultTableComponent } from './result-table/result-table.component'
|
||||||
|
import { SearchService } from 'src/app/core/services/search.service'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-browse',
|
selector: 'app-browse',
|
||||||
@@ -14,7 +15,7 @@ export class BrowseComponent implements AfterViewInit {
|
|||||||
@ViewChild('chartSidebar', { static: true }) chartSidebar: ChartSidebarComponent
|
@ViewChild('chartSidebar', { static: true }) chartSidebar: ChartSidebarComponent
|
||||||
@ViewChild('statusBar', { static: true }) statusBar: StatusBarComponent
|
@ViewChild('statusBar', { static: true }) statusBar: StatusBarComponent
|
||||||
|
|
||||||
constructor() { }
|
constructor(private searchService: SearchService) { }
|
||||||
|
|
||||||
ngAfterViewInit() {
|
ngAfterViewInit() {
|
||||||
const $tableColumn = $('#table-column')
|
const $tableColumn = $('#table-column')
|
||||||
@@ -27,14 +28,9 @@ export class BrowseComponent implements AfterViewInit {
|
|||||||
let pos = $tableColumn[0].scrollTop + $tableColumn[0].offsetHeight
|
let pos = $tableColumn[0].scrollTop + $tableColumn[0].offsetHeight
|
||||||
let max = $tableColumn[0].scrollHeight
|
let max = $tableColumn[0].scrollHeight
|
||||||
if (pos >= max - 5) {
|
if (pos >= max - 5) {
|
||||||
// TODO: load more results (should be debounced or something; wait until results have loaded before sending the request for more)
|
this.searchService.updateScroll()
|
||||||
console.log('UPDATE SCROLL')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
loadMoreResults() {
|
|
||||||
// TODO: use the same query as the current search, but append more results if there are any more to be viewed
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Injectable, EventEmitter } from '@angular/core'
|
import { Injectable, EventEmitter } from '@angular/core'
|
||||||
import { ElectronService } from './electron.service'
|
import { ElectronService } from './electron.service'
|
||||||
import { SearchType, SongResult } from 'src/electron/shared/interfaces/search.interface'
|
import { SearchType, SongResult, SongSearch } from 'src/electron/shared/interfaces/search.interface'
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@@ -10,11 +10,24 @@ export class SearchService {
|
|||||||
private resultsChangedEmitter = new EventEmitter<SongResult[]>() // For when any results change
|
private resultsChangedEmitter = new EventEmitter<SongResult[]>() // For when any results change
|
||||||
private newResultsEmitter = new EventEmitter<SongResult[]>() // For when a new search happens
|
private newResultsEmitter = new EventEmitter<SongResult[]>() // For when a new search happens
|
||||||
private results: SongResult[] = []
|
private results: SongResult[] = []
|
||||||
|
private awaitingResults = false
|
||||||
|
private currentQuery: SongSearch
|
||||||
|
private allResultsVisible = true
|
||||||
|
|
||||||
constructor(private electronService: ElectronService) { }
|
constructor(private electronService: ElectronService) { }
|
||||||
|
|
||||||
async newSearch(query: string) {
|
async newSearch(query: string) {
|
||||||
this.results = await this.electronService.invoke('song-search', { query, type: SearchType.Any })
|
this.awaitingResults = true
|
||||||
|
this.currentQuery = { query, type: SearchType.Any, offset: 0, length: 20 + 1 } // TODO: make length a setting
|
||||||
|
this.results = await this.electronService.invoke('song-search', this.currentQuery)
|
||||||
|
if (this.results.length > 20) {
|
||||||
|
this.results.splice(20, 1)
|
||||||
|
this.allResultsVisible = false
|
||||||
|
} else {
|
||||||
|
this.allResultsVisible = true
|
||||||
|
}
|
||||||
|
this.awaitingResults = false
|
||||||
|
|
||||||
this.newResultsEmitter.emit(this.results)
|
this.newResultsEmitter.emit(this.results)
|
||||||
this.resultsChangedEmitter.emit(this.results)
|
this.resultsChangedEmitter.emit(this.results)
|
||||||
}
|
}
|
||||||
@@ -30,4 +43,22 @@ export class SearchService {
|
|||||||
get resultCount() {
|
get resultCount() {
|
||||||
return this.results.length
|
return this.results.length
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async updateScroll() {
|
||||||
|
if (!this.awaitingResults && !this.allResultsVisible) {
|
||||||
|
this.awaitingResults = true
|
||||||
|
this.currentQuery.offset += 20
|
||||||
|
const newResults = await this.electronService.invoke('song-search', this.currentQuery)
|
||||||
|
if (newResults.length > 20) {
|
||||||
|
newResults.splice(20, 1)
|
||||||
|
this.allResultsVisible = false
|
||||||
|
} else {
|
||||||
|
this.allResultsVisible = true
|
||||||
|
}
|
||||||
|
this.results.push(...newResults)
|
||||||
|
this.awaitingResults = false
|
||||||
|
|
||||||
|
this.resultsChangedEmitter.emit(this.results)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class SearchHandler implements IPCInvokeHandler<'song-search'> {
|
|||||||
*/
|
*/
|
||||||
private getSearchQuery(search: SongSearch) {
|
private getSearchQuery(search: SongSearch) {
|
||||||
switch (search.type) {
|
switch (search.type) {
|
||||||
case SearchType.Any: return this.getGeneralSearchQuery(search.query)
|
case SearchType.Any: return this.getGeneralSearchQuery(search)
|
||||||
default: return '<<<ERROR>>>' // TODO: add more search types
|
default: return '<<<ERROR>>>' // TODO: add more search types
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -31,12 +31,12 @@ class SearchHandler implements IPCInvokeHandler<'song-search'> {
|
|||||||
/**
|
/**
|
||||||
* @returns a database query that returns the top 20 songs that match `search`.
|
* @returns a database query that returns the top 20 songs that match `search`.
|
||||||
*/
|
*/
|
||||||
private getGeneralSearchQuery(searchString: string) {
|
private getGeneralSearchQuery(search: SongSearch) {
|
||||||
return `
|
return `
|
||||||
SELECT id, name, artist, album, genre, year
|
SELECT id, name, artist, album, genre, year
|
||||||
FROM Song
|
FROM Song
|
||||||
WHERE MATCH (name,artist,album,genre) AGAINST (${escape(searchString)}) > 0
|
WHERE MATCH (name,artist,album,genre) AGAINST (${escape(search.query)}) > 0
|
||||||
LIMIT ${20} OFFSET ${0};
|
LIMIT ${search.length} OFFSET ${search.offset};
|
||||||
` // TODO: add parameters for the limit and offset
|
` // TODO: add parameters for the limit and offset
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
export interface SongSearch {
|
export interface SongSearch {
|
||||||
query: string
|
query: string
|
||||||
type: SearchType
|
type: SearchType
|
||||||
|
offset: number
|
||||||
|
length: number
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user