diff options
Diffstat (limited to 'ui.js')
-rw-r--r-- | ui.js | 151 |
1 files changed, 146 insertions, 5 deletions
diff --git a/ui.js b/ui.js index a167dab..8d89722 100644 --- a/ui.js +++ b/ui.js @@ -32,6 +32,11 @@ const { } = require('./playlist-utils') const { + updateRestoredTracksUsingPlaylists, + getWaitingTrackData +} = require('./serialized-backend') + +const { ui: { Dialog, DisplayElement, @@ -54,7 +59,7 @@ const { } = require('tui-lib') /* text editor features disabled because theyre very much incomplete and havent - * gotten much use from me or anyonea afaik! + * gotten much use from me or anyone afaik! const TuiTextEditor = require('tui-text-editor') */ @@ -191,6 +196,8 @@ class AppElement extends FocusElement { this.isPartyHost = false this.enableAutoDJ = false + this.playlistSources = [] + this.config = Object.assign({ canControlPlayback: true, canControlQueue: true, @@ -238,6 +245,18 @@ class AppElement extends FocusElement { }) */ + this.logPane = new Pane() + this.addChild(this.logPane) + + this.log = new Log() + this.logPane.addChild(this.log) + this.logPane.visible = false + + this.log.on('log-message', () => { + this.logPane.visible = true + this.fixLayout() + }) + if (!this.config.showTabberPane) { this.tabberPane.visible = false } @@ -430,12 +449,13 @@ class AppElement extends FocusElement { bindListeners() { for (const key of [ - 'handlePlaying', + 'handlePlayingDetails', 'handleReceivedTimeData', 'handleProcessMetadataProgress', 'handleQueueUpdated', 'handleAddedQueuePlayer', 'handleRemovedQueuePlayer', + 'handleLogMessage', 'handleSetLoopQueueAtEnd' ]) { this[key] = this[key].bind(this) @@ -469,7 +489,7 @@ class AppElement extends FocusElement { PIE.on('toggle pause', () => PIE.queuePlayer.togglePause()) queuePlayer.on('received time data', this.handleReceivedTimeData) - queuePlayer.on('playing', this.handlePlaying) + queuePlayer.on('playing details', this.handlePlayingDetails) queuePlayer.on('queue updated', this.handleQueueUpdated) } @@ -498,7 +518,7 @@ class AppElement extends FocusElement { } queuePlayer.removeListener('receivedTimeData', this.handleReceivedTimeData) - queuePlayer.removeListener('playing', this.handlePlaying) + queuePlayer.removeListener('playing details', this.handlePlayingDetails) queuePlayer.removeListener('queue updated', this.handleQueueUpdated) queuePlayer.stopPlaying() } @@ -507,6 +527,7 @@ class AppElement extends FocusElement { this.backend.on('processMetadata progress', this.handleProcessMetadataProgress) this.backend.on('added queue player', this.handleAddedQueuePlayer) this.backend.on('removed queue player', this.handleRemovedQueuePlayer) + this.backend.on('log message', this.handleLogMessage) this.backend.on('set-loop-queue-at-end', this.handleSetLoopQueueAtEnd) } @@ -514,6 +535,7 @@ class AppElement extends FocusElement { this.backend.removeListener('processMetadata progress', this.handleProcessMetadataProgress) this.backend.removeListener('added queue player', this.handleAddedQueuePlayer) this.backend.removeListener('removed queue player', this.handleRemovedQueuePlayer) + this.backend.removeListener('log message', this.handleLogMessage) this.backend.removeListener('set-loop-queue-at-end', this.handleSetLoopQueueAtEnd) } @@ -528,11 +550,15 @@ class AppElement extends FocusElement { } } + handleLogMessage(messageInfo) { + this.log.newLogMessage(messageInfo) + } + handleSetLoopQueueAtEnd() { this.updateQueueLengthLabel() } - async handlePlaying(track, oldTrack, queuePlayer) { + async handlePlayingDetails(track, oldTrack, queuePlayer) { const PIE = this.getPlaybackInfoElementForQueuePlayer(queuePlayer) if (PIE) { PIE.updateTrack() @@ -1216,6 +1242,9 @@ class AppElement extends FocusElement { grouplike = await processSmartPlaylist(grouplike) + this.playlistSources.push(grouplike) + updateRestoredTracksUsingPlaylists(this.backend, this.playlistSources) + if (!this.tabber.currentElement || newTab && this.tabber.currentElement.grouplike) { const grouplikeListing = this.newGrouplikeListing() grouplikeListing.loadGrouplike(grouplike) @@ -1329,10 +1358,21 @@ class AppElement extends FocusElement { } */ + if (this.logPane.visible) { + this.logPane.w = leftWidth + this.logPane.h = 6 + this.log.fillParent() + this.log.fixAllLayout() + } + if (this.tabberPane.visible) { this.tabberPane.w = leftWidth this.tabberPane.y = bottomY this.tabberPane.h = topY - this.tabberPane.y + if (this.logPane.visible) { + this.tabberPane.h -= this.logPane.h + this.logPane.y = this.tabberPane.bottom + } /* if (this.textInfoPane.visible) { this.tabberPane.h -= this.textInfoPane.h @@ -3531,6 +3571,7 @@ class PlaybackInfoElement extends FocusElement { refreshTrackText(maxNameWidth = Infinity) { const { playingTrack } = this.queuePlayer + const waitingTrackData = getWaitingTrackData(this.queuePlayer) if (playingTrack) { this.currentTrack = playingTrack const { name } = playingTrack @@ -3542,6 +3583,11 @@ class PlaybackInfoElement extends FocusElement { this.progressBarLabel.text = '' this.progressTextLabel.text = '(Starting..)' this.timeData = {} + } else if (waitingTrackData) { + const { name } = waitingTrackData + this.clearInfoText() + this.trackNameLabel.text = name + this.progressTextLabel.text = '(Waiting to play, once found in playlist source.)' } else { this.clearInfoText() } @@ -4554,4 +4600,99 @@ class NotesTextEditor extends TuiTextEditor { } */ +class Log extends ListScrollForm { + constructor() { + super('vertical') + } + + newLogMessage(messageInfo) { + if (this.inputs.length === 10) { + this.removeInput(this.inputs[0]) + } + + if (messageInfo.mayCombine) { + // If a message is specified to "combine", it'll replace an immediately + // previous message of the same code and sender. + const previous = this.inputs[this.inputs.length - 1] + if ( + previous && + previous.info.code === messageInfo.code && + previous.info.sender === messageInfo.sender + ) { + // If the code and sender match, just remove the previous message. + // It'll be replaced by the one we're about to add! + this.removeInput(previous) + } + } + + const logMessage = new LogMessage(messageInfo) + this.addInput(logMessage) + this.fixLayout() + this.scrollToEnd() + this.emit('log-message', logMessage) + return logMessage + } +} + +class LogMessage extends FocusElement { + constructor(info) { + super() + + this.info = info + + const { + text, + isVerbose = false + } = info + + this.label = new LogMessageLabel(text, isVerbose) + this.addChild(this.label) + } + + fixLayout() { + this.w = this.parent.contentW + this.label.w = this.contentW + this.h = this.label.h + } + + clicked(button) { + if (button === 'left') { + this.root.select(this) + return false + } + } +} + +class LogMessageLabel extends WrapLabel { + constructor(text, isVerbose = false) { + super(text) + + this.isVerbose = isVerbose + } + + writeTextTo(writable) { + const w = this.w + const lines = this.getWrappedLines() + for (let i = 0; i < lines.length; i++) { + const text = this.processFormatting(lines[i]) + writable.write(ansi.moveCursor(this.absTop + i, this.absLeft)) + writable.write(text) + const width = ansi.measureColumns(text) + if (width < w && this.textAttributes.length) { + writable.write(ansi.setAttributes([ansi.A_RESET, ...this.textAttributes])) + writable.write(' '.repeat(w - width)) + } + } + } + + set textAttributes(val) {} + + get textAttributes() { + return [ + this.parent.isSelected ? 40 : null, + this.isVerbose ? 2 : null + ].filter(x => x !== null) + } +} + module.exports = AppElement |