diff options
author | Florrie <towerofnix@gmail.com> | 2018-12-21 11:26:29 -0400 |
---|---|---|
committer | Florrie <towerofnix@gmail.com> | 2018-12-21 11:35:54 -0400 |
commit | 391a5b1329190c40aaa6c17f0281bab27eee8ce3 (patch) | |
tree | 07b3d5315bdb4bc9cfb376eb7a0d778765a4f295 | |
parent | 8438f8319149dae9f594a57eb0807ba2f8bba7d8 (diff) |
Move menu behavior out of grouplike item elements
This also makes it so that the selected options in whereControl and orderControl stay the same when you open the context menu on a different item, browse a different group, etc.
-rw-r--r-- | ui.js | 190 |
1 files changed, 95 insertions, 95 deletions
diff --git a/ui.js b/ui.js index 3496d97..038c008 100644 --- a/ui.js +++ b/ui.js @@ -94,6 +94,19 @@ class AppElement extends FocusElement { */ this.menu = new ContextMenu() this.addChild(this.menu) + + this.whereControl = new InlineListPickerElement('Where?', [ + {value: 'next', label: 'After current song'}, + {value: 'end', label: 'At end of queue'}, + {value: 'distribute-evenly', label: 'Distributed across queue evenly'}, + {value: 'distribute-randomly', label: 'Distributed across queue randomly'} + ]) + + this.orderControl = new InlineListPickerElement('Order?', [ + {value: 'shuffle', label: 'Shuffle all'}, + {value: 'shuffle-groups', label: 'Shuffle order of groups'}, + {value: 'normal', label: 'In order'} + ]) } selected() { @@ -107,36 +120,8 @@ class AppElement extends FocusElement { grouplikeListing.on('download', item => this.downloadGrouplikeItem(item)) grouplikeListing.on('browse', item => grouplikeListing.loadGrouplike(item)) - grouplikeListing.on('menu', (item, opts) => this.menu.show(opts)) - - grouplikeListing.on('queue', (item, {where = 'end', order = 'normal', play = false} = {}) => { - if (isGroup(item)) { - if (order === 'shuffle') { - item = {items: shuffleArray(flattenGrouplike(item).items)} - } else if (order === 'shuffle-groups') { - item = shuffleOrderOfGroups(item) - } - } - - if (where === 'next' || where === 'end') { - let afterItem = null - if (where === 'next') { - afterItem = this.playingTrack - } - - this.queueGrouplikeItem(item, afterItem, { - movePlayingTrack: order === 'normal' - }) - } else if (where.startsWith('distribute-')) { - this.distributeQueueGrouplikeItem(item, where.slice('distribute-'.length)) - } - - if (play) { - this.playGrouplikeItem(item) - } - }) - - grouplikeListing.on('unqueue', item => this.unqueueGrouplikeItem(item)) + grouplikeListing.on('menu', (item, el) => this.showMenuForItemElement(el)) + grouplikeListing.on('queue', (item, opts) => this.handleQueueOptions(item, opts)) const updateListingsFor = item => { for (const grouplikeListing of this.tabber.tabberElements) { @@ -241,7 +226,54 @@ class AppElement extends FocusElement { } grouplikeListing.pathElement.on('select', item => handleSelectFromPathElement(item)) + } + + showMenuForItemElement(el) { + const emitControls = play => () => { + this.handleQueueOptions(item, { + where: this.whereControl.curValue, + order: this.orderControl.curValue, + play: play + }) + } + + const { item, isGroup, isMarked } = el + const { editMode } = this + const anyMarked = editMode && this.markGrouplike.items.length > 0 + this.menu.show({ + x: el.absLeft, + y: el.absTop + 1, + items: [ + // A label that just shows some brief information about the item. + isGroup && {label: + `("${item.name}" -` + + ` ${item.items.length} item${item.items.length === 1 ? '' : 's'}` + + `, ${countTotalItems(item)} total` + + ')'}, + + // The actual controls! + {divider: true}, + // TODO: Don't emit these on the element (and hence receive them from + // the listing) - instead, handle their behavior directly. We'll want + // to move the "mark"/"paste" (etc) code into separate functions, + // instead of just defining their behavior inside the listing event + // handlers. + editMode && {label: isMarked ? 'Unmark' : 'Mark', action: () => el.emit('mark')}, + anyMarked && {label: 'Paste (above)', action: () => el.emit('paste', {where: 'above'})}, + anyMarked && {label: 'Paste (below)', action: () => el.emit('paste', {where: 'below'})}, + // anyMarked && !this.isReal && {label: 'Paste', action: () => this.emit('paste')}, // No "above" or "elow" in the label because the "fake" item/row will be replaced (it'll disappear, since there'll be an item in the group) + editMode && {divider: true}, + + {element: this.whereControl}, + {element: this.orderControl}, + {label: 'Play!', action: emitControls(true)}, + {label: 'Queue!', action: emitControls(false)}, + {divider: true}, + + {label: 'Remove from queue', action: () => this.unqueueGrouplikeItem(item)} + ] + }) } async handlePlaylistSource(source, newTab = false) { @@ -450,7 +482,37 @@ class AppElement extends FocusElement { this.player.kill() } - async queueGrouplikeItem(topItem, afterItem = null, {movePlayingTrack = true} = {}) { + // TODO: I'd like to name/incorporate this function better.. for now it's + // just directly moved from the old event listener on grouplikeListings for + // 'queue'. + handleQueueOptions(item, {where = 'end', order = 'normal', play = false} = {}) { + if (isGroup(item)) { + if (order === 'shuffle') { + item = {items: shuffleArray(flattenGrouplike(item).items)} + } else if (order === 'shuffle-groups') { + item = shuffleOrderOfGroups(item) + } + } + + if (where === 'next' || where === 'end') { + let afterItem = null + if (where === 'next') { + afterItem = this.playingTrack + } + + this.queueGrouplikeItem(item, afterItem, { + movePlayingTrack: order === 'normal' + }) + } else if (where.startsWith('distribute-')) { + this.distributeQueueGrouplikeItem(item, where.slice('distribute-'.length)) + } + + if (play) { + this.playGrouplikeItem(item) + } + } + + queueGrouplikeItem(topItem, afterItem = null, {movePlayingTrack = true} = {}) { const newTrackIndex = this.queueGrouplike.items.length // The position which new tracks should be added at, if afterItem is @@ -1236,19 +1298,6 @@ class InteractiveGrouplikeItemElement extends BasicGrouplikeItemElement { super(item.name) this.item = item this.recordStore = recordStore - - this.whereControl = new InlineListPickerElement('Where?', [ - {value: 'next', label: 'After current song'}, - {value: 'end', label: 'At end of queue'}, - {value: 'distribute-evenly', label: 'Distributed across queue evenly'}, - {value: 'distribute-randomly', label: 'Distributed across queue randomly'} - ]) - - this.orderControl = new InlineListPickerElement('Order?', [ - {value: 'shuffle', label: 'Shuffle all'}, - {value: 'shuffle-groups', label: 'Shuffle order of groups'}, - {value: 'normal', label: 'In order'} - ]) } drawTo(writable) { @@ -1272,7 +1321,7 @@ class InteractiveGrouplikeItemElement extends BasicGrouplikeItemElement { } else if (telc.isCaselessLetter(keyBuf, 'x')) { this.emit('remove') } else if (telc.isCaselessLetter(keyBuf, 'm') || telc.isCaselessLetter(keyBuf, 'f')) { - this.showMenu() + this.emit('menu', this) } } @@ -1290,60 +1339,11 @@ class InteractiveGrouplikeItemElement extends BasicGrouplikeItemElement { return false } else if (button === 'right') { this.parent.selectInput(this) - this.showMenu() + this.emit('menu', this) return false } } - showMenu() { - const editMode = this.recordStore.app.editMode - const anyMarked = editMode && !!this.recordStore.app.markGrouplike.items.length - this.emit('menu', { - x: this.absLeft, - y: this.absTop + 1, - items: [ - // A label that just shows some brief information about the item. - this.isGroup && {label: - `("${this.item.name}" -` + - ` ${this.item.items.length} item${this.item.items.length === 1 ? '' : 's'}` + - `, ${countTotalItems(this.item)} total` + - ')'}, - - // The actual controls! - {divider: true}, - editMode && {label: this.isMarked ? 'Unmark' : 'Mark', action: () => this.emit('mark')}, - anyMarked && {label: 'Paste (above)', action: () => this.emit('paste', {where: 'above'})}, - anyMarked && {label: 'Paste (below)', action: () => this.emit('paste', {where: 'below'})}, - // anyMarked && !this.isReal && {label: 'Paste', action: () => this.emit('paste')}, // No "above" or "elow" in the label because the "fake" item/row will be replaced (it'll disappear, since there'll be an item in the group) - editMode && {divider: true}, - - {element: this.whereControl}, - {element: this.orderControl}, - {label: 'Play!', action: () => this.playWithControls()}, - {label: 'Queue!', action: () => this.queueWithControls()}, - {divider: true}, - - {label: 'Remove from queue', action: () => this.emit('unqueue')} - ] - }) - } - - playWithControls() { - this.emitControls(true) - } - - queueWithControls() { - this.emitControls(false) - } - - emitControls(play) { - this.emit('queue', { - where: this.whereControl.curValue, - order: this.orderControl.curValue, - play: play - }) - } - writeStatus(writable) { if (this.isGroup) { // The ANSI attributes here will apply to the rest of the line, too. |