Polished sidebar

This commit is contained in:
Geomitron
2020-03-05 16:06:51 -05:00
parent db02710b37
commit 80c467ed7e
3 changed files with 101 additions and 65 deletions

View File

@@ -21,7 +21,7 @@ export class BrowseComponent {
this.resultTable.results = results this.resultTable.results = results
this.resultTable.onNewSearch() this.resultTable.onNewSearch()
this.resultTable.checkAll(false) this.resultTable.checkAll(false)
this.chartSidebar.selectedVersion = undefined this.chartSidebar.selectVersion(undefined)
this.statusBar.resultCount = results.length this.statusBar.resultCount = results.length
this.statusBar.selectedResults = [] this.statusBar.selectedResults = []
} }

View File

@@ -1,6 +1,6 @@
<div *ngIf="selectedVersion" class="ui fluid card"> <div *ngIf="selectedVersion" class="ui fluid card">
<div class="ui placeholder" [ngClass]="{'placeholder': !albumArtBuffer}"> <div class="ui placeholder" [ngClass]="{'placeholder': albumArtSrc == ''}">
<img class="ui square image" [src]="getAlbumArtSrc()"> <img class="ui square image" [src]="albumArtSrc">
</div> </div>
<div *ngIf="charts.length > 1" id="chartDropdown" class="ui fluid selection dropdown"> <div *ngIf="charts.length > 1" id="chartDropdown" class="ui fluid selection dropdown">
<input type="hidden" name="Chart"> <input type="hidden" name="Chart">
@@ -15,24 +15,19 @@
</div> </div>
</div> </div>
<div id="textPanel" class="content"> <div id="textPanel" class="content">
<span class="header">{{selectedVersion?.avTagName}}</span> <span class="header">{{selectedVersion.avTagName}}</span>
<div class="description"> <div class="description">
<div><b>{{charterPlural}}</b> {{selectedVersion?.charters}}</div> <div><b>{{charterPlural}}</b> {{selectedVersion.charters}}</div>
<div *ngIf="selectedVersion?.tags"><b>Tags:</b> {{selectedVersion.tags}}</div> <div *ngIf="selectedVersion.tags"><b>Tags:</b> {{selectedVersion.tags}}</div>
<div><b>Audio Length:</b> {{getSongLength()}}</div> <div><b>Audio Length:</b> {{songLength}}</div>
<!-- TODO: add difficulty icons --> <!-- TODO: add difficulty icons -->
</div> </div>
</div> </div>
<div class="ui positive buttons"> <div class="ui positive buttons">
<div class="ui button" (click)="onDownloadClicked()">Download{{getVersions().length > 1 ? ' Latest' : ''}}</div> <div class="ui button" (click)="onDownloadClicked()">{{downloadButtonText}}</div>
<div *ngIf="getVersions().length > 1" id="versionDropdown" class="ui floating dropdown icon button"> <div *ngIf="getSelectedChartVersions().length > 1" id="versionDropdown" class="ui floating dropdown icon button">
<i class="dropdown icon"></i> <i class="dropdown icon"></i>
<div class="menu">
<div class="item">Version 1</div>
<div class="item">Version 2</div>
<div class="item">Version 3</div>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -15,38 +15,43 @@ export class ChartSidebarComponent {
private songResult: SongResult private songResult: SongResult
selectedVersion: VersionResult selectedVersion: VersionResult
charterPlural: string
albumArtBuffer: Buffer
charts: VersionResult[][] charts: VersionResult[][]
constructor(private electronService: ElectronService, private albumArtService: AlbumArtService, private downloadService: DownloadService) { } constructor(private electronService: ElectronService, private albumArtService: AlbumArtService, private downloadService: DownloadService) { }
/**
* Displays the information for the selected song.
*/
async onRowClicked(result: SongResult) { async onRowClicked(result: SongResult) {
if (this.songResult == undefined || result.id != this.songResult.id) { // Clicking the same row again will not reload
this.songResult = result this.songResult = result
const albumArt = this.albumArtService.getImage(result.id) const albumArt = this.albumArtService.getImage(result.id)
const results = await this.electronService.invoke('song-details', result.id) const results = await this.electronService.invoke('song-details', result.id)
this.charts = groupBy(results, 'chartID').sort((v1, v2) => v1[0].avTagName.length - v2[0].avTagName.length)
this.charts = groupBy(results, 'chartID') this.charts.forEach(chart => chart.sort((v1, v2) => v2.lastModified - v1.lastModified))
await this.selectChart(0)
this.initChartDropdown() this.initChartDropdown()
this.albumArtBuffer = await albumArt this.updateAlbumArtSrc(await albumArt)
}
} }
getAlbumArtSrc() { albumArtSrc = ''
if (this.albumArtBuffer) { /**
return 'data:image/jpg;base64,' + this.albumArtBuffer.toString('base64') * Updates the sidebar to display the album art.
*/
updateAlbumArtSrc(albumArtBuffer?: Buffer) {
if (albumArtBuffer) {
this.albumArtSrc = 'data:image/jpg;base64,' + albumArtBuffer.toString('base64')
} else { } else {
return '' this.albumArtSrc = ''
} }
} }
/** /**
* Initializes the chart dropdown from <this.charts> (or removes it if there's only one chart) * Initializes the chart dropdown from `this.charts` (or removes it if there's only one chart).
*/ */
private async initChartDropdown() { private initChartDropdown() {
this.switchChart(this.charts[0][0].chartID)
await new Promise<void>(resolve => setTimeout(() => resolve(), 0)) // Wait for *ngIf to update DOM
const values = this.charts.map(chart => { const values = this.charts.map(chart => {
const version = chart[0] const version = chart[0]
return { return {
@@ -57,31 +62,49 @@ export class ChartSidebarComponent {
}) })
const $chartDropdown = $('#chartDropdown') const $chartDropdown = $('#chartDropdown')
$chartDropdown.dropdown('setup menu', { values }) $chartDropdown.dropdown('setup menu', { values })
$chartDropdown.dropdown('setting', 'onChange', (chartID: number) => this.switchChart(chartID)) $chartDropdown.dropdown('setting', 'onChange', (chartID: number) => this.selectChart(chartID))
$chartDropdown.dropdown('set selected', values[0].value) $chartDropdown.dropdown('set selected', values[0].value)
} }
/** private async selectChart(chartID: number) {
* Updates the sidebar to display the metadata for the chart with <chartID>.
* @param chartID The ID of the chart to display.
*/
private switchChart(chartID: number) {
const chart = this.charts.find(chart => chart[0].chartID == chartID) const chart = this.charts.find(chart => chart[0].chartID == chartID)
this.selectedVersion = chart[0] await this.selectVersion(chart[0])
this.charterPlural = this.selectedVersion.charterIDs.split('&').length == 1 ? 'Charter:' : 'Charters:'
this.initVersionDropdown() this.initVersionDropdown()
} }
/**
* Updates the sidebar to display the metadata for `selectedVersion`.
*/
async selectVersion(selectedVersion: VersionResult) {
this.selectedVersion = selectedVersion
await new Promise<void>(resolve => setTimeout(() => resolve(), 0)) // Wait for *ngIf to update DOM
if (this.selectedVersion != undefined) {
this.updateCharterPlural()
this.updateSongLength()
this.updateDownloadButtonText()
}
}
charterPlural: string
/**
* Chooses to display 'Charter:' or 'Charters:'.
*/
updateCharterPlural() {
this.charterPlural = this.selectedVersion.charterIDs.split('&').length == 1 ? 'Charter:' : 'Charters:'
}
songLength: string
/** /**
* Converts <this.selectedVersion.song_length> into a readable duration. * Converts <this.selectedVersion.song_length> into a readable duration.
*/ */
getSongLength() { updateSongLength() {
if (this.selectedVersion.song_length == 0) { if (this.selectedVersion.song_length == 0) {
return 'Unknown' this.songLength = 'Unknown'
} }
let seconds = Math.round(this.selectedVersion.song_length / 1000) let seconds = Math.round(this.selectedVersion.song_length / 1000)
if (seconds < 60) { if (seconds < 60) {
return `${seconds} second${seconds == 1 ? '' : 's'}` this.songLength = `${seconds} second${seconds == 1 ? '' : 's'}`
} }
let minutes = Math.floor(seconds / 60) let minutes = Math.floor(seconds / 60)
let hours = 0 let hours = 0
@@ -90,38 +113,60 @@ export class ChartSidebarComponent {
minutes -= 60 minutes -= 60
} }
seconds = Math.floor(seconds % 60) seconds = Math.floor(seconds % 60)
return `${hours == 0 ? '' : hours + ':'}${minutes == 0 ? '' : minutes + ':'}${seconds < 10 ? '0' + seconds : seconds}` this.songLength = `${hours == 0 ? '' : hours + ':'}${minutes == 0 ? '' : minutes + ':'}${seconds < 10 ? '0' + seconds : seconds}`
}
downloadButtonText: string
/**
* Chooses the text to display on the download button.
*/
updateDownloadButtonText() {
if (this.getSelectedChartVersions().length <= 1) {
this.downloadButtonText = 'Download'
} else if (this.selectedVersion.versionID == this.selectedVersion.latestVersionID) {
this.downloadButtonText = 'Download Latest'
} else {
this.downloadButtonText = `Download (${this.getLastModifiedText(this.selectedVersion.lastModified)})`
}
} }
/** /**
* Initializes the version dropdown from <this.selectedVersion> (or removes it if there's only one version) * Initializes the version dropdown from `this.selectedVersion` (or removes it if there's only one version).
*/ */
private initVersionDropdown() { private initVersionDropdown() {
const $versionDropdown = $('#versionDropdown') const $versionDropdown = $('#versionDropdown')
const versions = this.getVersions() const versions = this.getSelectedChartVersions()
const values = versions.map(version => { const values = versions.map(version => ({
return {
value: version.versionID, value: version.versionID,
text: this.getLastModified(version.lastModified), text: this.getLastModifiedText(version.lastModified),
name: this.getLastModified(version.lastModified) name: this.getLastModifiedText(version.lastModified)
} }))
})
$versionDropdown.dropdown('setup menu', { values }) $versionDropdown.dropdown('setup menu', { values })
$versionDropdown.dropdown('setting', 'onChange', (versionID: number) => { $versionDropdown.dropdown('setting', 'onChange', (versionID: number) => {
console.log(`Selected version: ${versionID}`) this.selectVersion(versions.find(version => version.versionID == versionID))
this.selectedVersion = versions.find(version => version.versionID = versionID)
}) })
$versionDropdown.dropdown('set selected', values[0].value) $versionDropdown.dropdown('set selected', values[0].value)
} }
/**
* Returns the list of versions for the selected chart, sorted by `lastModified`.
*/
getSelectedChartVersions() {
return this.charts.find(chart => chart[0].chartID == this.selectedVersion.chartID)
}
/** /**
* Converts the <lastModified> value to a user-readable format. * Converts the <lastModified> value to a user-readable format.
* @param lastModified The UNIX timestamp for the lastModified date. * @param lastModified The UNIX timestamp for the lastModified date.
*/ */
private getLastModified(lastModified: number) { private getLastModifiedText(lastModified: number) {
return new Date(lastModified).toLocaleDateString() return new Date(lastModified).toLocaleDateString()
} }
/**
* Adds the selected version to the download queue.
*/
onDownloadClicked() { onDownloadClicked() {
this.downloadService.addDownload( this.downloadService.addDownload(
this.selectedVersion.versionID, { this.selectedVersion.versionID, {
@@ -131,8 +176,4 @@ export class ChartSidebarComponent {
links: JSON.parse(this.selectedVersion.downloadLink) links: JSON.parse(this.selectedVersion.downloadLink)
}) })
} }
getVersions() {
return this.charts.find(chart => chart[0].chartID == this.selectedVersion.chartID)
}
} }