update deps, better handling of a large playlist via {{ember-collection}}, fix linting issues
This commit is contained in:
parent
1a51f1f8a9
commit
f8293a7373
7 changed files with 548 additions and 440 deletions
|
|
@ -9,5 +9,9 @@ module.exports = {
|
|||
browser: true
|
||||
},
|
||||
rules: {
|
||||
}
|
||||
},
|
||||
globals: {
|
||||
chrome: false,
|
||||
introJs: false
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
524
web/yarn.lock
524
web/yarn.lock
File diff suppressed because it is too large
Load diff
Reference in a new issue