Difficulty info and source folder links

This commit is contained in:
Geomitron
2020-09-01 16:00:14 -04:00
parent b228948646
commit 1914ee9ab4
13 changed files with 149 additions and 10 deletions

View File

@@ -16,7 +16,22 @@
<div><b>{{charterPlural}}</b> {{selectedVersion.charters}}</div>
<div *ngIf="selectedVersion.tags"><b>Tags:</b> {{selectedVersion.tags}}</div>
<div><b>Audio Length:</b> {{songLength}}</div>
<!-- TODO: add difficulty icons -->
<div class="ui divider"></div>
<div class="ui horizontal list">
<div *ngFor="let difficulty of difficultiesList" class="item">
<img class="ui avatar image" src="/assets/images/instruments/{{difficulty.instrument}}">
<div class="content">
<div class="header">Diff: {{difficulty.diffNumber}}</div>
{{difficulty.chartedDifficulties}}
</div>
</div>
</div>
<div id="sourceLinks">
<a id="sourceLink" (click)="onSourceLinkClicked()">{{selectedVersion.driveData.source.sourceName}}</a>
<button *ngIf="shownFolderButton()" id="folderButton" class="mini ui icon button" (click)="onFolderButtonClicked()">
<i class="folder open outline icon"></i>
</button>
</div>
</div>
</div>

View File

@@ -12,7 +12,7 @@
overflow-y: auto;
}
#versionDropdown {
#versionDropdown, #folderButton {
max-width: min-content;
}
@@ -25,12 +25,29 @@
word-break: break-word;
}
#sourceLinks {
display: flex;
}
#sourceLink {
align-self: center;
flex-grow: 1;
}
#chartDropdownIcon, #versionDropdown {
display: flex;
flex-direction: column;
justify-content: center;
}
.ui.horizontal.list>.item {
margin-right: 12px;
}
.ui.divider {
margin: 4px 0;
}
#downloadButton {
width: min-content;
}

View File

@@ -1,13 +1,19 @@
import { Component, OnInit } from '@angular/core'
import { SongResult } from '../../../../electron/shared/interfaces/search.interface'
import { ElectronService } from '../../../core/services/electron.service'
import { VersionResult } from '../../../../electron/shared/interfaces/songDetails.interface'
import { VersionResult, getInstrumentIcon, Instrument, ChartedDifficulty } from '../../../../electron/shared/interfaces/songDetails.interface'
import { AlbumArtService } from '../../../core/services/album-art.service'
import { DownloadService } from '../../../core/services/download.service'
import { groupBy } from 'src/electron/shared/UtilFunctions'
import { SearchService } from 'src/app/core/services/search.service'
import { DomSanitizer, SafeUrl } from '@angular/platform-browser'
interface Difficulty {
instrument: string
diffNumber: string
chartedDifficulties: string
}
@Component({
selector: 'app-chart-sidebar',
templateUrl: './chart-sidebar.component.html',
@@ -110,6 +116,7 @@ export class ChartSidebarComponent implements OnInit {
if (this.selectedVersion != undefined) {
this.updateCharterPlural()
this.updateSongLength()
this.updateDifficultiesList()
this.updateDownloadButtonText()
}
}
@@ -118,7 +125,7 @@ export class ChartSidebarComponent implements OnInit {
/**
* Chooses to display 'Charter:' or 'Charters:'.
*/
updateCharterPlural() {
private updateCharterPlural() {
this.charterPlural = this.selectedVersion.charterIDs.split('&').length == 1 ? 'Charter:' : 'Charters:'
}
@@ -126,7 +133,7 @@ export class ChartSidebarComponent implements OnInit {
/**
* Converts `this.selectedVersion.chartMetadata.length` into a readable duration.
*/
updateSongLength() {
private updateSongLength() {
let seconds = this.selectedVersion.songLength
if (seconds < 60) { this.songLength = `${seconds} second${seconds == 1 ? '' : 's'}`; return }
let minutes = Math.floor(seconds / 60)
@@ -139,11 +146,50 @@ export class ChartSidebarComponent implements OnInit {
this.songLength = `${hours == 0 ? '' : hours + ':'}${minutes == 0 ? '' : minutes + ':'}${seconds < 10 ? '0' + seconds : seconds}`
}
difficultiesList: Difficulty[]
/**
* Updates `dfficultiesList` with the difficulty information for the selected version.
*/
private updateDifficultiesList() {
const instruments = Object.keys(this.selectedVersion.chartData.noteCounts) as Instrument[]
this.difficultiesList = []
for (const instrument of instruments) {
this.difficultiesList.push({
instrument: getInstrumentIcon(instrument),
diffNumber: this.getDiffNumber(instrument),
chartedDifficulties: this.getChartedDifficultiesText(instrument)
})
}
}
/**
* @returns a string describing the difficulty number in the selected version.
*/
private getDiffNumber(instrument: Instrument) {
const diffNumber: number = this.selectedVersion[`diff_${instrument}`]
return diffNumber == -1 || diffNumber == undefined ? 'Unknown' : String(diffNumber)
}
/**
* @returns a string describing the list of charted difficulties in the selected version.
*/
private getChartedDifficultiesText(instrument: Instrument) {
const difficulties = Object.keys(this.selectedVersion.chartData.noteCounts[instrument]) as ChartedDifficulty[]
if (difficulties.length == 4) { return 'Full Difficulty' }
const difficultyNames = []
if (difficulties.includes('x')) { difficultyNames.push('Expert') }
if (difficulties.includes('h')) { difficultyNames.push('Hard') }
if (difficulties.includes('m')) { difficultyNames.push('Medium') }
if (difficulties.includes('e')) { difficultyNames.push('Easy') }
return difficultyNames.join(', ')
}
downloadButtonText: string
/**
* Chooses the text to display on the download button.
*/
updateDownloadButtonText() {
private updateDownloadButtonText() {
this.downloadButtonText = 'Download'
if (this.selectedVersion.driveData.inChartPack) {
this.downloadButtonText += ' Chart Pack'
@@ -198,6 +244,29 @@ export class ChartSidebarComponent implements OnInit {
return `${month}/${day}/${year}`
}
/**
* Opens the proxy link or source folder in the default browser.
*/
onSourceLinkClicked() {
const source = this.selectedVersion.driveData.source
this.electronService.sendIPC('open-url', source.proxyLink ?? `https://drive.google.com/drive/folders/${source.sourceDriveID}`)
}
/**
* @returns `true` if the source folder button should be shown.
*/
shownFolderButton() {
const driveData = this.selectedVersion.driveData
return driveData.source.proxyLink || driveData.source.sourceDriveID != driveData.folderID
}
/**
* Opens the chart folder in the default browser.
*/
onFolderButtonClicked() {
this.electronService.sendIPC('open-url', `https://drive.google.com/drive/folders/${this.selectedVersion.driveData.folderID}`)
}
/**
* Adds the selected version to the download queue.
*/

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -0,0 +1 @@
<svg fill="#000" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" version="1.1" style="shape-rendering:geometricPrecision;text-rendering:geometricPrecision;image-rendering:optimizeQuality;" viewBox="0 0 1000 1000" x="0px" y="0px" fill-rule="evenodd" clip-rule="evenodd"><g transform="translate(75 100)"><path full="#fff" class="fil0" d="M164 131c-48,-13 -82,-88 -38,-119 44,-32 104,24 101,74 93,125 149,200 196,264 48,-64 103,-139 197,-264 -4,-50 57,-106 101,-74 44,31 10,106 -38,119 -58,83 -130,187 -205,294 58,78 123,166 254,342 37,51 -46,107 -81,58 -65,-89 -146,-204 -228,-322 -82,118 -163,233 -227,322 -36,49 -118,-7 -81,-58 131,-176 196,-264 253,-342 -74,-107 -146,-211 -204,-294zm241 346l-19 -27 -248 334c-13,19 21,43 34,25l233 -332zm36 -102l18 24 201 -286c2,-5 6,-8 12,-9 28,-5 54,-53 32,-69 -23,-16 -60,24 -55,53 1,4 -1,9 -4,12l-204 275zm233 434c14,18 48,-6 34,-25l-506 -684c-3,-3 -5,-8 -4,-12 5,-29 -32,-69 -55,-53 -22,16 3,64 32,69 5,1 10,4 12,9l487 696z"></path></g></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -0,0 +1,18 @@
import { IPCEmitHandler } from '../shared/IPCHandler'
import { shell } from 'electron'
/**
* Handles the 'open-url' event.
*/
class OpenURLHandler implements IPCEmitHandler<'open-url'> {
event: 'open-url' = 'open-url'
/**
* Opens `url` in the default browser.
*/
handler(url: string) {
shell.openExternal(url)
}
}
export const openURLHandler = new OpenURLHandler()

View File

@@ -115,7 +115,7 @@ class APIFileDownloader {
if (this.wasCanceled) { return }
this.startDownloadStream()
} else {
console.log(err)
console.log(JSON.stringify(err))
this.failDownload(downloadErrors.responseError(err ? (err.code ?? 'unknown') : 'unknown'))
}
}

View File

@@ -11,6 +11,7 @@ import { getSettingsHandler, setSettingsHandler } from '../ipc/SettingsHandler.i
import { googleLoginHandler, getAuthStatusHandler, googleLogoutHandler } from '../ipc/google/GoogleLoginHandler.ipc'
import { UpdateProgress, getCurrentVersionHandler, downloadUpdateHandler, quitAndInstallHandler, getUpdateAvailableHandler } from '../ipc/UpdateHandler.ipc'
import { UpdateInfo } from 'electron-updater'
import { openURLHandler } from '../ipc/OpenURLHandler.ipc'
/**
* To add a new IPC listener:
@@ -95,7 +96,8 @@ export function getIPCEmitHandlers(): IPCEmitHandler<keyof IPCEmitEvents>[] {
downloadHandler,
setSettingsHandler,
downloadUpdateHandler,
quitAndInstallHandler
quitAndInstallHandler,
openURLHandler
]
}
@@ -114,6 +116,7 @@ export type IPCEmitEvents = {
'update-downloaded': undefined
'download-update': undefined
'quit-and-install': undefined
'open-url': string
}
/**

View File

@@ -83,12 +83,28 @@ export interface ChartData {
is120: boolean
hasBrokenNotes: boolean
noteCounts: {
[instrument: string]: {
[difficulty: string]: number
[instrument in Instrument]: {
[difficulty in ChartedDifficulty]: number
}
}
/** number of seconds */
length: number
/** number of seconds */
effectiveLength: number
}
export type Instrument = 'guitar' | 'bass' | 'rhythm' | 'keys' | 'drums' | 'guitarghl' | 'bassghl' | 'vocals'
export type ChartedDifficulty = 'x' | 'h' | 'm' | 'e'
export function getInstrumentIcon(instrument: Instrument) {
switch(instrument) {
case 'guitar': return 'guitar.png'
case 'bass': return 'bass.png'
case 'rhythm': return 'guitar.png' // TODO: get unique icon
case 'keys': return 'keys.png'
case 'drums': return 'drums.svg'
case 'guitarghl': return 'guitarghl.png'
case 'bassghl': return 'bassghl.png'
case 'vocals': return 'guitar.png' // TODO: get unique icon
}
}