update deps, better handling of a large playlist via {{ember-collection}}, fix linting issues

This commit is contained in:
Egor 2017-11-23 23:36:01 -08:00
parent 1a51f1f8a9
commit f8293a7373
7 changed files with 548 additions and 440 deletions

View file

@ -9,5 +9,9 @@ module.exports = {
browser: true
},
rules: {
}
},
globals: {
chrome: false,
introJs: false
},
};

View file

@ -1,37 +0,0 @@
{
"predef": [
"document",
"window",
"-Promise",
"Dancer",
"ID3",
"FileAPIReader",
"SC",
"introJs"
],
"browser": true,
"boss": true,
"curly": true,
"debug": false,
"devel": true,
"eqeqeq": true,
"evil": true,
"forin": false,
"immed": false,
"laxbreak": false,
"newcap": true,
"noarg": true,
"noempty": false,
"nonew": false,
"nomen": false,
"onevar": false,
"plusplus": false,
"regexp": false,
"undef": true,
"sub": true,
"strict": false,
"white": false,
"eqnull": true,
"esversion": 6,
"unused": true
}

View file

@ -1,7 +1,6 @@
/*global chrome introJs*/
import Ember from 'ember';
const { A, Component, computed, isEmpty, isNone, run: { later, scheduleOnce }, inject, $, set } = Ember;
const { A, Component, computed, isEmpty, isNone, run: { later, scheduleOnce }, inject, $ } = Ember;
export default Component.extend({
classNames: ['container-fluid'],
@ -10,7 +9,7 @@ export default Component.extend({
firstVisitApp: true,
activeLights: A(),
tabList: ["Lights", "Music"],
tabList: ['Lights', 'Music'],
selectedTab: 1,
pauseLightUpdates: false,
@ -18,44 +17,45 @@ export default Component.extend({
notify: inject.service(),
dimmerOnClass: computed('dimmerOn', function () {
dimmerOnClass: computed('dimmerOn', function() {
return this.get('dimmerOn') ? 'dimmerOn md-menu-origin' : 'md-menu-origin';
}),
ready: computed('lightsData', 'trial', function () {
ready: computed('lightsData', 'trial', function() {
return this.get('trial') || !isNone(this.get('lightsData'));
}),
apiURL: computed('bridgeIp', 'bridgeUsername', function () {
apiURL: computed('bridgeIp', 'bridgeUsername', function() {
return 'http://' + this.get('bridgeIp') + '/api/' + this.get('bridgeUsername');
}),
tabData: computed('tabList', 'selectedTab', function () {
let tabData = [], selectedTab = this.get('selectedTab');
tabData: computed('tabList', 'selectedTab', function() {
let tabData = [],
selectedTab = this.get('selectedTab');
this.get('tabList').forEach(function (tab, i) {
this.get('tabList').forEach(function(tab, i) {
let selected = false;
if (i === selectedTab) {
selected = true;
}
tabData.push({ "name": tab, "selected": selected });
tabData.push({ name: tab, selected: selected });
});
return tabData;
}),
didInsertElement() {
if (!window.matchMedia || (window.matchMedia("(min-width: 768px)").matches)) {
if (!window.matchMedia || window.matchMedia('(min-width: 768px)').matches) {
// here's a weird way to automatically initialize bootstrap tooltips
let observer = new MutationObserver(function (mutations) {
let haveTooltip = !mutations.every(function (mutation) {
let observer = new MutationObserver(function(mutations) {
let haveTooltip = !mutations.every(function(mutation) {
return isEmpty(mutation.addedNodes) || isNone(mutation.addedNodes[0].classList) || mutation.addedNodes[0].classList.contains('tooltip');
});
if (haveTooltip) {
scheduleOnce('afterRender', function () {
scheduleOnce('afterRender', function() {
$('.bootstrap-tooltip').tooltip();
});
}
@ -68,14 +68,13 @@ export default Component.extend({
init() {
this._super(...arguments);
let isChrome = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor),
storage = this.get('storage'),
let storage = this.get('storage'),
firstVisitApp = storage.get('huegasm.firstVisitApp');
if (!isEmpty(firstVisitApp)) {
this.set('firstVisitApp', false);
}
if (!this.get('trial')) {
this.updateLightData();
setInterval(this.updateLightData.bind(this), 2000);
@ -94,9 +93,13 @@ export default Component.extend({
this.get('notify').warning({ html: '<div class="alert alert-warning" role="alert">Error retrieving data from your lights. Yikes.</div>' });
this.set('displayFailure', false);
later(this, function () {
this.set('displayFailure', true);
}, 30000);
later(
this,
function() {
this.set('displayFailure', true);
},
30000
);
}
};
@ -113,10 +116,10 @@ export default Component.extend({
actions: {
tryAndroid() {
window.open("https://play.google.com/store/apps/details?id=com.hoboman313.huegasm", '_blank');
window.open('https://play.google.com/store/apps/details?id=com.hoboman313.huegasm', '_blank');
},
tryExtension() {
chrome.webstore.install("https://chrome.google.com/webstore/detail/mbjanbdhcpohhfecjgbdpcfhnnbofooj");
chrome.webstore.install('https://chrome.google.com/webstore/detail/mbjanbdhcpohhfecjgbdpcfhnnbofooj');
},
changeTab(tabName) {
let index = this.get('tabList').indexOf(tabName);
@ -140,7 +143,7 @@ export default Component.extend({
location.reload();
},
email() {
window.open("mailto:huegasm.app@gmail.com", '_blank');
window.open('mailto:huegasm.app@gmail.com', '_blank');
},
startIntro() {
let intro = introJs(),
@ -157,13 +160,15 @@ export default Component.extend({
},
{
element: '#music-tab',
intro: 'This is the music player. You\'ll use this to play music and synchronize it with your active lights.<br><br>' +
'<i><b>TIP</b>: Control which lights are active through the <b>Lights</b> tab.</i>'
intro:
"This is the music player. You'll use this to play music and synchronize it with your active lights.<br><br>" +
'<i><b>TIP</b>: Control which lights are active through the <b>Lights</b> tab.</i>'
},
{
element: '#playlist',
intro: 'You can add and select music to play from your playlist here. You may listen to local audio files or stream music from Soundcloud.<br><br>' +
'<i><b>TIP</b>: Songs added through Soundcloud will be saved for when you visit this page again.</i>'
intro:
'You can add and select music to play from your playlist here. You may listen to local audio files or stream music from Soundcloud.<br><br>' +
'<i><b>TIP</b>: Songs added through Soundcloud will be saved for when you visit this page again.</i>'
},
{
element: $('#playlist md-menu')[0],
@ -171,48 +176,52 @@ export default Component.extend({
},
{
element: '#player-area',
intro: 'The audio playback may be controlled with the controls here. Basic music visualization effects may be shown here by selecting them from the menu (eyeball icon in the bottom right).'
intro:
'The audio playback may be controlled with the controls here. Basic music visualization effects may be shown here by selecting them from the menu (eyeball icon in the bottom right).'
},
{
element: '#beat-option-row',
intro: '<b>Sensitivity</b> - The sensitivity of the beat detector (higher sensitivity results in more registered beats)<br>' +
'<b>Color Range</b> - The color range that the lights may change to on beat.<br>' +
'<b>Brightness Range</b> - The minimum (off-beat) and maximum (on-beat) brightness of the lights.<br>' +
'<b>Flashing Transitions</b> - Quickly flash the lights on beat<br>' +
'<b>Colorloop</b> - Slowly cycle the lights through all the colors while the music is playing<br>' +
'<b>Ambience</b> - When turned on, your lights will sporadically change color.<br>' +
'<b>Blackout</b> - When turned on, your lghts will turn off after flashing on a detected beat.<br><br>' +
'<i><b>TIP</b>: Your sensitivity settings are saved per song as indicated by the red star icon in the top left corner.</i>',
intro:
'<b>Sensitivity</b> - The sensitivity of the beat detector (higher sensitivity results in more registered beats)<br>' +
'<b>Color Range</b> - The color range that the lights may change to on beat.<br>' +
'<b>Brightness Range</b> - The minimum (off-beat) and maximum (on-beat) brightness of the lights.<br>' +
'<b>Flashing Transitions</b> - Quickly flash the lights on beat<br>' +
'<b>Colorloop</b> - Slowly cycle the lights through all the colors while the music is playing<br>' +
'<b>Ambience</b> - When turned on, your lights will sporadically change color.<br>' +
'<b>Blackout</b> - When turned on, your lghts will turn off after flashing on a detected beat.<br><br>' +
'<i><b>TIP</b>: Your sensitivity settings are saved per song as indicated by the red star icon in the top left corner.</i>',
position: 'top'
},
{
element: '#beat-container',
intro: 'An interactive speaker that will bump when a beat is registered. <br><br>' +
'<i><b>TIP</b>: Click on the center of the speaker to simulate a beat.</i>',
intro: 'An interactive speaker that will bump when a beat is registered. <br><br>' + '<i><b>TIP</b>: Click on the center of the speaker to simulate a beat.</i>',
position: 'top'
},
{
element: '#lights-tab',
intro: 'This is the lights tab. Here you\'ll be able to change various light properties:<br>' +
'<b>Power</b> - Turn the selected lights on/off<br>' +
'<b>Brightness</b> - The brightness level of the selected lights<br>' +
'<b>Color</b> - The color of the selected lights<br>' +
'<b>Strobe</b> - Selected lights will flash in sequential order<br>' +
'<b>Colorloop</b> - Selected lights will slowly cycle through all the colors<br>' +
'<b>Randomize Hues</b> - Randomize the hues (colors) of your selected lights<br>'
intro:
"This is the lights tab. Here you'll be able to change various light properties:<br>" +
'<b>Power</b> - Turn the selected lights on/off<br>' +
'<b>Brightness</b> - The brightness level of the selected lights<br>' +
'<b>Color</b> - The color of the selected lights<br>' +
'<b>Strobe</b> - Selected lights will flash in sequential order<br>' +
'<b>Colorloop</b> - Selected lights will slowly cycle through all the colors<br>' +
'<b>Randomize Hues</b> - Randomize the hues (colors) of your selected lights<br>'
},
{
element: '#active-lights',
intro: 'These icons represent the hue lights in your system. Active lights will be controlled by the application while the inactive lights will have a red X over them and will not be controlled.<br>' +
'You may toggle a light\'s state by clicking on it.'
intro:
'These icons represent the hue lights in your system. Active lights will be controlled by the application while the inactive lights will have a red X over them and will not be controlled.<br>' +
"You may toggle a light's state by clicking on it."
},
{
element: $('#navigation .ember-basic-dropdown-trigger')[0],
intro: 'A few miscellaneous settings can be found here.<br><br>' +
'<b>WARNING</b>: clearing application settings will restore the application to its original state. This will even delete your playlist and any saved song beat preferences.'
intro:
'A few miscellaneous settings can be found here.<br><br>' +
'<b>WARNING</b>: clearing application settings will restore the application to its original state. This will even delete your playlist and any saved song beat preferences.'
},
{
intro: 'And that\'s it...Hope you enjoy the application. ;)'
intro: "And that's it...Hope you enjoy the application. ;)"
}
]
});
@ -221,11 +230,25 @@ export default Component.extend({
$('body').velocity('scroll', { duration: 200 });
});
intro.onchange((element) => {
if (element.id === '' || element.id === 'music-tab' || element.id === 'playlist' || element.id === 'player-area' || element.id === 'beat-option-row' || element.id === 'beat-option-button-group' || element.id === 'beat-container' || element.id === 'using-mic-audio-tooltip' || element.nodeName === 'MD-MENU') {
$('.navigation-item').eq(1).click();
intro.onchange(element => {
if (
element.id === '' ||
element.id === 'music-tab' ||
element.id === 'playlist' ||
element.id === 'player-area' ||
element.id === 'beat-option-row' ||
element.id === 'beat-option-button-group' ||
element.id === 'beat-container' ||
element.id === 'using-mic-audio-tooltip' ||
element.nodeName === 'MD-MENU'
) {
$('.navigation-item')
.eq(1)
.click();
} else {
$('.navigation-item').eq(0).click();
$('.navigation-item')
.eq(0)
.click();
}
if (element.id === 'music-tab' || element.id === 'playlist' || element.id === 'player-area') {
@ -238,22 +261,32 @@ export default Component.extend({
});
// skip hidden/missing elements
intro.onafterchange((element) => {
let elem = $(element);
if (elem.html() === '<!---->') {
$('.introjs-nextbutton').click();
}
intro
.onafterchange(element => {
let elem = $(element);
if (elem.html() === '<!---->') {
$('.introjs-nextbutton').click();
}
if (element.id === '') {
later(this, () => {
$('body').velocity('scroll');
}, 500);
} else {
later(this, () => {
$('.introjs-tooltip').velocity('scroll', { offset: -100 });
}, 500);
}
}).start();
if (element.id === '') {
later(
this,
() => {
$('body').velocity('scroll');
},
500
);
} else {
later(
this,
() => {
$('.introjs-tooltip').velocity('scroll', { offset: -100 });
},
500
);
}
})
.start();
},
closeNotificationModal() {
this.set('firstVisitApp', false);

View file

@ -21,7 +21,7 @@ export default Mixin.create({
values: [0, 0.5],
density: 10,
format: {
to: function (value) {
to: function(value) {
if (value === 0) {
value = 'High';
} else {
@ -30,7 +30,9 @@ export default Mixin.create({
return value;
},
from: function (value) { return value; }
from: function(value) {
return value;
}
}
}
},
@ -43,7 +45,7 @@ export default Mixin.create({
values: [0, 25500, 46920, 65535],
density: 10,
format: {
to: function (value) {
to: function(value) {
if (value === 0 || value === 65535) {
value = 'Red';
} else if (value === 25500) {
@ -54,7 +56,9 @@ export default Mixin.create({
return value;
},
from: function (value) { return value; }
from: function(value) {
return value;
}
}
}
},
@ -67,7 +71,7 @@ export default Mixin.create({
values: [1, 63, 127, 190, 254],
density: 10,
format: {
to: function (value) {
to: function(value) {
if (value === 63) {
value = 25;
} else if (value === 127) {
@ -80,7 +84,9 @@ export default Mixin.create({
return value;
},
from: function (value) { return value; }
from: function(value) {
return value;
}
}
}
}
@ -91,6 +97,7 @@ export default Mixin.create({
hueRange: [0, 65535],
brightnessRange: [1, 254],
oldThreshold: null,
playlistColumns: [100],
playQueuePointer: -1,
playQueue: A(),
@ -136,9 +143,11 @@ export default Mixin.create({
SC_CLIENT_ID: 'aeec0034f58ecd85c2bd1deaecc41594',
scUserNotSupportedHtml: '<div class="alert alert-danger" role="alert">SoundCloud user URLs are not supported.</div>',
tooManySoundCloudFuckUps: '<div class="alert alert-danger" role="alert">The SoundCloud API is not seving the audio properly. More details <a href="https://www.soundcloudcommunity.com/soundcloud/topics/some-soundcloud-cdn-hosted-tracks-dont-have-access-control-allow-origin-header" target="_blank" rel="noopener noreferrer">HERE</a>.</div>',
tooManySoundCloudFuckUps:
'<div class="alert alert-danger" role="alert">The SoundCloud API is not seving the audio properly. More details <a href="https://www.soundcloudcommunity.com/soundcloud/topics/some-soundcloud-cdn-hosted-tracks-dont-have-access-control-allow-origin-header" target="_blank" rel="noopener noreferrer">HERE</a>.</div>',
notStreamableHtml(fileNames) {
let html = '<div class="alert alert-danger" role="alert">The following file(s) could not be added because they are not allowed to be streamed:<br>' + fileNames.toString().replace(/,/g, '<br>') + '</div>';
let html =
'<div class="alert alert-danger" role="alert">The following file(s) could not be added because they are not allowed to be streamed:<br>' + fileNames.toString().replace(/,/g, '<br>') + '</div>';
return html;
},
@ -152,7 +161,7 @@ export default Mixin.create({
return '<div class="alert alert-danger" role="alert">Failed to decode file (' + fileName + ').</div>';
},
scUrl: computed('playQueuePointer', 'playQueue.[]', function () {
scUrl: computed('playQueuePointer', 'playQueue.[]', function() {
let rtn = null,
currentSong = this.get('playQueue')[this.get('playQueuePointer')];
@ -165,11 +174,11 @@ export default Mixin.create({
playQueueEmpty: computed.empty('playQueue'),
playQueueNotEmpty: computed.notEmpty('playQueue'),
playQueueMultiple: computed('playQueue.[]', function () {
playQueueMultiple: computed('playQueue.[]', function() {
return this.get('playQueue').length > 1;
}),
seekPosition: computed('timeElapsed', 'timeTotal', function () {
seekPosition: computed('timeElapsed', 'timeTotal', function() {
let timeTotal = this.get('timeTotal'),
timeElapsed = this.get('timeElapsed');
@ -180,7 +189,7 @@ export default Mixin.create({
return timeElapsed / timeTotal * 100;
}),
largeArtworkPic: computed('playQueuePointer', 'currentVisName', function () {
largeArtworkPic: computed('playQueuePointer', 'currentVisName', function() {
let pic = '',
currentVisName = this.get('currentVisName'),
playQueuePointer = this.get('playQueuePointer'),
@ -200,7 +209,7 @@ export default Mixin.create({
return pic;
}),
repeatIcon: computed('repeat', function () {
repeatIcon: computed('repeat', function() {
if (this.get('repeat') === 2) {
return 'repeat-one';
}
@ -208,7 +217,7 @@ export default Mixin.create({
return 'repeat';
}),
playingIcon: computed('playing', function () {
playingIcon: computed('playing', function() {
if (this.get('playing')) {
return 'pause';
} else if (this.get('timeElapsed') === this.get('timeTotal') && this.get('timeTotal') !== 0) {
@ -218,7 +227,7 @@ export default Mixin.create({
}
}),
playListAreaClass: computed('dragging', 'draggingOverPlayListArea', 'dimmerOn', function () {
playListAreaClass: computed('dragging', 'draggingOverPlayListArea', 'dimmerOn', function() {
let classes = 'pointer';
if (this.get('dragging')) {
@ -236,11 +245,11 @@ export default Mixin.create({
return classes;
}),
dimmerOnClass: computed('dimmerOn', function () {
dimmerOnClass: computed('dimmerOn', function() {
return this.get('dimmerOn') ? 'dimmerOn' : null;
}),
volumeMutedClass: computed('volumeMuted', function () {
volumeMutedClass: computed('volumeMuted', function() {
let classes = 'player-control-icon volumeButton';
if (this.get('volumeMuted')) {
@ -250,29 +259,29 @@ export default Mixin.create({
return classes;
}),
repeatClass: computed('repeat', function () {
repeatClass: computed('repeat', function() {
return this.get('repeat') !== 0 ? 'player-control-icon active' : 'player-control-icon';
}),
shuffleClass: computed('shuffle', function () {
shuffleClass: computed('shuffle', function() {
return this.get('shuffle') ? 'player-control-icon active' : 'player-control-icon';
}),
volumeIcon: computed('volumeMuted', 'volume', function () {
volumeIcon: computed('volumeMuted', 'volume', function() {
let volume = this.get('volume');
if (this.get('volumeMuted')) {
return "volume-off";
return 'volume-off';
} else if (volume >= 70) {
return "volume-up";
return 'volume-up';
} else if (volume > 10) {
return "volume-down";
return 'volume-down';
} else {
return 'volume-mute';
}
}),
beatDetectionAreaArrowIcon: computed('playerBottomDisplayed', function () {
beatDetectionAreaArrowIcon: computed('playerBottomDisplayed', function() {
if (!this.get('playerBottomDisplayed')) {
return 'keyboard-arrow-down';
} else {
@ -280,20 +289,20 @@ export default Mixin.create({
}
}),
timeElapsedTxt: computed('timeElapsed', function () {
timeElapsedTxt: computed('timeElapsed', function() {
return this.formatTime(this.get('timeElapsed'));
}),
timeTotalTxt: computed('timeTotal', function () {
timeTotalTxt: computed('timeTotal', function() {
return this.formatTime(this.get('timeTotal'));
}),
onPlayQueueChange: observer('playQueue.length', function () {
onPlayQueueChange: observer('playQueue.length', function() {
let playQueueLength = this.get('playQueue.length');
if (playQueueLength > this.get('oldPlayQueueLength')) {
run.once(this, () => {
run.next(this, function () {
run.next(this, function() {
$(`.track${playQueueLength - 1}`).velocity('scroll', { container: $('#play-list-area'), duration: 200 });
});
});
@ -302,21 +311,21 @@ export default Mixin.create({
this.set('oldPlayQueueLength', playQueueLength);
}),
playerAreaClickIcon: computed('playing', function () {
playerAreaClickIcon: computed('playing', function() {
if (this.get('playing')) {
return 'play-arrow';
} else {
return 'pause';
}
}),
onOptionChange: observer('flashingTransitions', 'playQueue.[]', 'playQueuePointer', 'ambienceMode', 'blackoutMode', function (self, option) {
onOptionChange: observer('flashingTransitions', 'playQueue.[]', 'playQueuePointer', 'ambienceMode', 'blackoutMode', function(self, option) {
option = option.replace('.[]', '');
let value = this.get(option);
// can't really save local music
if (option === 'playQueue') {
value = value.filter((song) => {
value = value.filter(song => {
return !song.url.startsWith('blob:');
});
} else if (option === 'blackoutMode') {
@ -328,7 +337,7 @@ playerAreaClickIcon: computed('playing', function () {
}
if (this.get('playing')) {
this.get('activeLights').forEach((light) => {
this.get('activeLights').forEach(light => {
$.ajax(this.get('apiURL') + '/lights/' + light + '/state', {
data: JSON.stringify(options),
contentType: 'application/json',
@ -343,71 +352,92 @@ playerAreaClickIcon: computed('playing', function () {
this.get('storage').set('huegasm.' + option, value);
}),
onRepeatChange: on('init', observer('repeat', function () {
let tooltipTxt = 'Repeat all', type = 'repeat';
onRepeatChange: on(
'init',
observer('repeat', function() {
let tooltipTxt = 'Repeat all',
type = 'repeat';
if (this.get(type) === 1) {
tooltipTxt = 'Repeat one';
} else if (this.get(type) === 2) {
tooltipTxt = 'Repeat off';
}
if (this.get(type) === 1) {
tooltipTxt = 'Repeat one';
} else if (this.get(type) === 2) {
tooltipTxt = 'Repeat off';
}
this.changeTooltipText(type, tooltipTxt);
})),
this.changeTooltipText(type, tooltipTxt);
})
),
onShuffleChange: on('init', observer('shuffle', function () {
let tooltipTxt = 'Shuffle', type = 'shuffle';
onShuffleChange: on(
'init',
observer('shuffle', function() {
let tooltipTxt = 'Shuffle',
type = 'shuffle';
if (this.get(type)) {
this.get('shufflePlayed').clear();
tooltipTxt = 'Unshuffle';
}
if (this.get(type)) {
this.get('shufflePlayed').clear();
tooltipTxt = 'Unshuffle';
}
this.changeTooltipText(type, tooltipTxt);
})),
this.changeTooltipText(type, tooltipTxt);
})
),
onVolumeMutedChange: on('init', observer('volumeMuted', function () {
let tooltipTxt = 'Mute', type = 'volumeMuted',
volumeMuted = this.get(type), dancer = this.get('dancer'),
volume = 0;
onVolumeMutedChange: on(
'init',
observer('volumeMuted', function() {
let tooltipTxt = 'Mute',
type = 'volumeMuted',
volumeMuted = this.get(type),
dancer = this.get('dancer'),
volume = 0;
if (volumeMuted) {
tooltipTxt = 'Unmute';
volume = 0;
} else {
volume = this.get('volume') / 100;
}
if (volumeMuted) {
tooltipTxt = 'Unmute';
volume = 0;
} else {
volume = this.get('volume') / 100;
}
if (this.get('playing')) {
dancer.setVolume(volume);
}
if (this.get('playing')) {
dancer.setVolume(volume);
}
this.changeTooltipText(type, tooltipTxt);
})),
this.changeTooltipText(type, tooltipTxt);
})
),
onPrevChange: on('init', observer('timeElapsed', 'playQueueNotEmpty', 'playQueue.[]', function () {
if (this.get('playQueueNotEmpty')) {
let tooltipTxt = 'Previous', type = 'prev';
onPrevChange: on(
'init',
observer('timeElapsed', 'playQueueNotEmpty', 'playQueue.[]', function() {
if (this.get('playQueueNotEmpty')) {
let tooltipTxt = 'Previous',
type = 'prev';
if (this.get('timeElapsed') > 5 || this.get('playQueue').length === 1) {
if (this.get('timeElapsed') > 5 || this.get('playQueue').length === 1) {
tooltipTxt = 'Replay';
}
this.changeTooltipText(type, tooltipTxt);
}
})
),
onPlayingChange: on(
'init',
observer('playing', function() {
let tooltipTxt = 'Play',
type = 'playing';
if (this.get(type)) {
tooltipTxt = 'Pause';
} else if (this.get('timeElapsed') === this.get('timeTotal') && this.get('timeTotal') !== 0) {
tooltipTxt = 'Replay';
}
this.changeTooltipText(type, tooltipTxt);
}
})),
onPlayingChange: on('init', observer('playing', function () {
let tooltipTxt = 'Play', type = 'playing';
if (this.get(type)) {
tooltipTxt = 'Pause';
} else if (this.get('timeElapsed') === this.get('timeTotal') && this.get('timeTotal') !== 0) {
tooltipTxt = 'Replay';
}
this.changeTooltipText(type, tooltipTxt);
})),
})
),
changeTooltipText(type, text) {
// change the tooltip text if it's already visible
@ -424,5 +454,7 @@ playerAreaClickIcon: computed('playing', function () {
return this.pad(Math.floor(time / 60), 2) + ':' + this.pad(time % 60, 2);
},
pad(num, size) { return ('000000000' + num).substr(-size); }
pad(num, size) {
return ('000000000' + num).substr(-size);
}
});

View file

@ -94,33 +94,36 @@
{{paper-icon "library-music" class=dimmerOnClass}}
{{/if}}
{{#each playQueue as |item index|}}
{{#ember-collection
items=playQueue
cell-layout=(percentage-columns-layout playQueue.length playlistColumns 62) as |item|
}}
<div class="playlist-item pointer track{{index}} {{if (eq index playQueuePointer) "active"}} {{if dragging "hidden"}}" {{action "goToSong" index true bubbles=false}}>
{{#if item.picture}}
<img class="album-art" src= {{item.picture}}>
{{#if item.picture}}
<img class="album-art" src= {{item.picture}}>
{{else}}
<img class="album-art" src="assets/images/missingArtwork.png">
{{/if}}
<div class="song-info">
{{#if item.title}}
<div class="song-title">{{item.title}}</div>
<div class="song-artist">
{{#if item.artistUrl}}
<a href="#" {{action "gotoURL" item.artistUrl bubbles=false}}>{{item.artist}}</a>
{{else}}
{{item.artist}}
{{/if}}
</div>
{{else}}
<img class="album-art" src="assets/images/missingArtwork.png">
{{item.fileName}}
{{/if}}
<div class="song-info">
{{#if item.title}}
<div class="song-title">{{item.title}}</div>
<div class="song-artist">
{{#if item.artistUrl}}
<a href="#" {{action "gotoURL" item.artistUrl bubbles=false}}>{{item.artist}}</a>
{{else}}
{{item.artist}}
{{/if}}
</div>
{{else}}
{{item.fileName}}
{{/if}}
</div>
<span data-toggle="tooltip" data-placement="top auto" data-title="Remove" data-container="body" class="audio-remove-button pointer bootstrap-tooltip"
{{action "removeAudio" index bubbles=false}}>{{paper-icon "close" classNames="close"}}</span>
</div>
{{/each}}
<span data-toggle="tooltip" data-placement="top auto" data-title="Remove" data-container="body" class="audio-remove-button pointer bootstrap-tooltip"
{{action "removeAudio" index bubbles=false}}>{{paper-icon "close" classNames="close"}}</span>
</div>
{{/ember-collection}}
</div>
</div>
</div>

View file

@ -37,6 +37,7 @@
"ember-cli-shims": "^1.0.2",
"ember-cli-sri": "^2.1.0",
"ember-cli-uglify": "^2.0.0",
"ember-collection": "^1.0.0-alpha.7",
"ember-export-application-global": "^2.0.0",
"ember-inline-svg": "^0.1.7",
"ember-load-initializers": "^1.0.0",

File diff suppressed because it is too large Load diff