modernizing part 2
This commit is contained in:
parent
dc152fb2b3
commit
228b1cb417
14 changed files with 1293 additions and 1208 deletions
|
|
@ -1,14 +1,48 @@
|
|||
import Em from 'ember';
|
||||
import Ember from 'ember';
|
||||
|
||||
const {
|
||||
Component,
|
||||
observer,
|
||||
computed,
|
||||
isEmpty,
|
||||
isNone,
|
||||
$
|
||||
} = Ember;
|
||||
|
||||
export default Component.extend({
|
||||
groupName: null,
|
||||
selectedLights: [],
|
||||
|
||||
onIsShowingModalChange: observer('isShowingModal', function(){
|
||||
if(this.get('isShowingModal')){
|
||||
this.setProperties({
|
||||
selectedLights: [],
|
||||
groupName: null
|
||||
});
|
||||
}
|
||||
}),
|
||||
|
||||
saveDisabled: computed('groupName', 'selectedLights.[]', function(){
|
||||
return isNone(this.get('groupName')) || isEmpty(this.get('selectedLights')) || isEmpty(this.get('groupName').trim());
|
||||
}),
|
||||
|
||||
didInsertElement: function() {
|
||||
$(document).keypress((event) => {
|
||||
if(!this.get('saveDisabled') && event.which === 13) {
|
||||
this.send('save');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
export default Em.Component.extend({
|
||||
actions: {
|
||||
close: function(){
|
||||
this.sendAction();
|
||||
},
|
||||
save: function(){
|
||||
var newGroupData = {"name": this.get('groupName'), "lights": this.get('selectedLights')}, newGroupsData = this.get('groupsData');
|
||||
let newGroupData = {"name": this.get('groupName'), "lights": this.get('selectedLights')},
|
||||
newGroupsData = this.get('groupsData');
|
||||
|
||||
Em.$.ajax(this.get('apiURL') + '/groups', {
|
||||
$.ajax(this.get('apiURL') + '/groups', {
|
||||
data: JSON.stringify(newGroupData),
|
||||
contentType: 'application/json',
|
||||
type: 'POST'
|
||||
|
|
@ -24,7 +58,7 @@ export default Em.Component.extend({
|
|||
this.sendAction();
|
||||
},
|
||||
clickLight: function(id) {
|
||||
var selectedLights = this.get('selectedLights');
|
||||
let selectedLights = this.get('selectedLights');
|
||||
|
||||
if(selectedLights.contains(id)){
|
||||
selectedLights.removeObject(id);
|
||||
|
|
@ -32,30 +66,5 @@ export default Em.Component.extend({
|
|||
selectedLights.pushObject(id);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
didInsertElement: function() {
|
||||
Em.$(document).keypress((event) => {
|
||||
if(!this.get('saveDisabled') && event.which === 13) {
|
||||
this.send('save');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
groupName: null,
|
||||
|
||||
selectedLights: [],
|
||||
|
||||
onIsShowingModalChange: function(){
|
||||
if(this.get('isShowingModal')){
|
||||
this.setProperties({
|
||||
selectedLights: [],
|
||||
groupName: null
|
||||
});
|
||||
}
|
||||
}.observes('isShowingModal'),
|
||||
|
||||
saveDisabled: function(){
|
||||
return Em.isNone(this.get('groupName')) || Em.isEmpty(this.get('selectedLights')) || Em.isEmpty(this.get('groupName').trim());
|
||||
}.property('groupName', 'selectedLights.[]')
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,39 @@
|
|||
import Em from 'ember';
|
||||
import Ember from 'ember';
|
||||
|
||||
const {
|
||||
Component,
|
||||
observer,
|
||||
computed,
|
||||
isEmpty,
|
||||
isNone,
|
||||
$
|
||||
} = Ember;
|
||||
|
||||
export default Component.extend({
|
||||
url: null,
|
||||
|
||||
onIsShowingModalChange: observer('isShowingModal', function(){
|
||||
if(this.get('isShowingModal')){
|
||||
this.set('url', null);
|
||||
setTimeout(()=>{
|
||||
$('md-input-container input').focus();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
}),
|
||||
|
||||
saveDisabled: computed('url', function(){
|
||||
return isNone(this.get('url')) || isEmpty(this.get('url').trim());
|
||||
}),
|
||||
|
||||
didInsertElement: function() {
|
||||
$(document).keypress((event)=>{
|
||||
if(!this.get('saveDisabled') && event.which === 13) {
|
||||
this.send('add');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
export default Em.Component.extend({
|
||||
actions: {
|
||||
close () {
|
||||
this.sendAction();
|
||||
|
|
@ -8,31 +41,5 @@ export default Em.Component.extend({
|
|||
add (){
|
||||
this.sendAction('action', this.get('url'));
|
||||
}
|
||||
},
|
||||
|
||||
url: null,
|
||||
|
||||
onIsShowingModalChange: function(){
|
||||
if(this.get('isShowingModal')){
|
||||
this.set('url', null);
|
||||
setTimeout(()=>{
|
||||
Em.$('md-input-container input').focus();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
}.observes('isShowingModal'),
|
||||
|
||||
didInsertElement: function() {
|
||||
var self = this;
|
||||
|
||||
Em.$(document).keypress(function(event) {
|
||||
if(!self.get('saveDisabled') && event.which === 13) {
|
||||
self.send('add');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
saveDisabled: function(){
|
||||
return Em.isNone(this.get('url')) || Em.isEmpty(this.get('url').trim());
|
||||
}.property('url')
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,65 +1,51 @@
|
|||
import Em from 'ember';
|
||||
import Ember from 'ember';
|
||||
|
||||
export default Em.Component.extend({
|
||||
const {
|
||||
Component,
|
||||
observer,
|
||||
computed,
|
||||
on,
|
||||
isNone,
|
||||
$
|
||||
} = Ember;
|
||||
|
||||
export default Component.extend({
|
||||
classNames: ['container', 'bridgeFinder'],
|
||||
|
||||
bridgeIp: null,
|
||||
trial: false,
|
||||
bridgeUsername: null,
|
||||
|
||||
bridgeFindStatus: null,
|
||||
bridgeFindSuccess: Em.computed.equal('bridgeFindStatus', 'success'),
|
||||
bridgeFindMultiple: Em.computed.equal('bridgeFindStatus', 'multiple'),
|
||||
bridgeFindFail: Em.computed.equal('bridgeFindStatus', 'fail'),
|
||||
|
||||
// 30 seconds
|
||||
bridgeUsernamePingMaxTime: 30000,
|
||||
bridgeFindSuccess: computed.equal('bridgeFindStatus', 'success'),
|
||||
bridgeFindMultiple: computed.equal('bridgeFindStatus', 'multiple'),
|
||||
bridgeFindFail: computed.equal('bridgeFindStatus', 'fail'),
|
||||
bridgeUsernamePingMaxTime: 30000, // 30 seconds
|
||||
bridgeUsernamePingIntervalTime: 1000,
|
||||
bridgeUserNamePingIntervalProgress: 0,
|
||||
|
||||
bridgePingIntervalHandle: null,
|
||||
bridgeAuthenticateReachedStatus: null,
|
||||
|
||||
manualBridgeIp: null,
|
||||
manualBridgeIpNotFound: false,
|
||||
multipleBridgeIps: [],
|
||||
error: false,
|
||||
|
||||
actions: {
|
||||
retry(){
|
||||
this.onBridgeIpChange();
|
||||
},
|
||||
isAuthenticating: computed('bridgePingIntervalHandle', function(){
|
||||
return this.get('bridgePingIntervalHandle') !== null;
|
||||
}),
|
||||
|
||||
findBridgeByIp() {
|
||||
var manualBridgeIp = this.get('manualBridgeIp');
|
||||
|
||||
if (manualBridgeIp.toLowerCase() === 'trial' || manualBridgeIp.toLowerCase() === 'offline') {
|
||||
this.setProperties({
|
||||
trial: true,
|
||||
bridgeIp: 'trial',
|
||||
bridgeUsername: 'trial'
|
||||
});
|
||||
} else {
|
||||
Em.$.ajax('http://' + manualBridgeIp + '/api', {
|
||||
data: JSON.stringify({"devicetype": "huegasm"}),
|
||||
contentType: 'application/json',
|
||||
type: 'POST'
|
||||
}).fail(() => {
|
||||
this.set('manualBridgeIpNotFound', true);
|
||||
setTimeout(() => { this.set('manualBridgeIpNotFound', false); }, 5000);
|
||||
}).then(() => {
|
||||
this.set('bridgeIp', manualBridgeIp);
|
||||
});
|
||||
}
|
||||
// try to authenticate against the bridge here
|
||||
onBridgeIpChange: on('init', observer('bridgeIp', function(){
|
||||
if(!this.get('trial') && !this.get('isAuthenticating')) {
|
||||
this.setProperties({
|
||||
bridgePingIntervalHandle: setInterval(this.pingBridgeUser.bind(this), this.get('bridgeUsernamePingIntervalTime')),
|
||||
bridgeUserNamePingIntervalProgress: 0
|
||||
});
|
||||
}
|
||||
},
|
||||
})),
|
||||
|
||||
didInsertElement() {
|
||||
var self = this;
|
||||
|
||||
Em.$(document).keypress(function(event) {
|
||||
if(!Em.isNone(self.get('manualBridgeIp')) && event.which === 13) {
|
||||
self.send('findBridgeByIp');
|
||||
$(document).keypress((event)=>{
|
||||
if(!isNone(this.get('manualBridgeIp')) && event.which === 13) {
|
||||
this.send('findBridgeByIp');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
|
@ -69,18 +55,18 @@ export default Em.Component.extend({
|
|||
this._super();
|
||||
|
||||
if(this.get('bridgeIp') === null) {
|
||||
Em.$.ajax('https://www.meethue.com/api/nupnp', {
|
||||
$.ajax('https://www.meethue.com/api/nupnp', {
|
||||
timeout: 30000
|
||||
})
|
||||
.done((result, status)=> {
|
||||
var bridgeFindStatus = 'fail';
|
||||
let bridgeFindStatus = 'fail';
|
||||
|
||||
if (status === 'success' && result.length === 1) {
|
||||
this.set('bridgeIp', result[0].internalipaddress);
|
||||
this.get('storage').set('huegasm.bridgeIp', result[0].internalipaddress);
|
||||
bridgeFindStatus = 'success';
|
||||
} else if (result.length > 1) {
|
||||
var multipleBridgeIps = this.get('multipleBridgeIps');
|
||||
let multipleBridgeIps = this.get('multipleBridgeIps');
|
||||
|
||||
result.forEach(function (item) {
|
||||
multipleBridgeIps.pushObject(item.internalipaddress);
|
||||
|
|
@ -99,23 +85,13 @@ export default Em.Component.extend({
|
|||
}
|
||||
},
|
||||
|
||||
// try to authenticate against the bridge here
|
||||
onBridgeIpChange: function () {
|
||||
if(!this.get('trial') && !this.get('isAuthenticating')) {
|
||||
this.setProperties({
|
||||
bridgePingIntervalHandle: setInterval(this.pingBridgeUser.bind(this), this.get('bridgeUsernamePingIntervalTime')),
|
||||
bridgeUserNamePingIntervalProgress: 0
|
||||
});
|
||||
}
|
||||
}.observes('bridgeIp').on('init'),
|
||||
|
||||
pingBridgeUser() {
|
||||
var bridgeIp = this.get('bridgeIp'),
|
||||
let bridgeIp = this.get('bridgeIp'),
|
||||
bridgeUserNamePingIntervalProgress = this.get('bridgeUserNamePingIntervalProgress'),
|
||||
bridgeUsernamePingMaxTime = this.get('bridgeUsernamePingMaxTime');
|
||||
|
||||
if (bridgeIp !== null && bridgeUserNamePingIntervalProgress < 100) {
|
||||
Em.$.ajax('http://' + bridgeIp + '/api', {
|
||||
$.ajax('http://' + bridgeIp + '/api', {
|
||||
data: JSON.stringify({"devicetype": "huegasm"}),
|
||||
contentType: 'application/json',
|
||||
type: 'POST'
|
||||
|
|
@ -143,7 +119,32 @@ export default Em.Component.extend({
|
|||
this.set('bridgePingIntervalHandle', null);
|
||||
},
|
||||
|
||||
isAuthenticating: function(){
|
||||
return this.get('bridgePingIntervalHandle') !== null;
|
||||
}.property('bridgePingIntervalHandle')
|
||||
actions: {
|
||||
retry(){
|
||||
this.onBridgeIpChange();
|
||||
},
|
||||
|
||||
findBridgeByIp() {
|
||||
let manualBridgeIp = this.get('manualBridgeIp');
|
||||
|
||||
if (manualBridgeIp.toLowerCase() === 'trial' || manualBridgeIp.toLowerCase() === 'offline') {
|
||||
this.setProperties({
|
||||
trial: true,
|
||||
bridgeIp: 'trial',
|
||||
bridgeUsername: 'trial'
|
||||
});
|
||||
} else {
|
||||
$.ajax('http://' + manualBridgeIp + '/api', {
|
||||
data: JSON.stringify({"devicetype": "huegasm"}),
|
||||
contentType: 'application/json',
|
||||
type: 'POST'
|
||||
}).fail(() => {
|
||||
this.set('manualBridgeIpNotFound', true);
|
||||
setTimeout(() => { this.set('manualBridgeIpNotFound', false); }, 5000);
|
||||
}).then(() => {
|
||||
this.set('bridgeIp', manualBridgeIp);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,12 +1,16 @@
|
|||
import Em from 'ember';
|
||||
import Ember from 'ember';
|
||||
|
||||
export default Em.Component.extend({
|
||||
const {
|
||||
Component,
|
||||
$
|
||||
} = Ember;
|
||||
|
||||
export default Component.extend({
|
||||
classNames: ['colorpicker'],
|
||||
|
||||
rgb: null,
|
||||
|
||||
canvas: null,
|
||||
canvasContext: null,
|
||||
pressingDown: false,
|
||||
|
||||
mouseUp(){
|
||||
this.set('pressingDown', false);
|
||||
|
|
@ -19,12 +23,13 @@ export default Em.Component.extend({
|
|||
},
|
||||
|
||||
mouseDown(event){
|
||||
var canvasOffset = Em.$(this.get('canvas')).offset();
|
||||
var canvasX = Math.floor(event.pageX - canvasOffset.left), canvasY = Math.floor(event.pageY - canvasOffset.top);
|
||||
let canvasOffset = $(this.get('canvas')).offset(),
|
||||
canvasX = Math.floor(event.pageX - canvasOffset.left),
|
||||
canvasY = Math.floor(event.pageY - canvasOffset.top);
|
||||
|
||||
// get current pixel
|
||||
var imageData = this.get('canvasContext').getImageData(canvasX, canvasY, 1, 1);
|
||||
var pixel = imageData.data;
|
||||
let imageData = this.get('canvasContext').getImageData(canvasX, canvasY, 1, 1),
|
||||
pixel = imageData.data;
|
||||
|
||||
this.set('pressingDown', true);
|
||||
|
||||
|
|
@ -33,12 +38,10 @@ export default Em.Component.extend({
|
|||
}
|
||||
},
|
||||
|
||||
pressingDown: false,
|
||||
|
||||
// https://dzone.com/articles/creating-your-own-html5
|
||||
didInsertElement(){
|
||||
// handle color changes
|
||||
var canvas = Em.$('#picker')[0],
|
||||
let canvas = $('#picker')[0],
|
||||
canvasContext = canvas.getContext('2d'),
|
||||
image = new Image();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,19 +1,24 @@
|
|||
import Em from 'ember';
|
||||
import Ember from 'ember';
|
||||
|
||||
export default Em.Component.extend({
|
||||
const {
|
||||
Component,
|
||||
$
|
||||
} = Ember;
|
||||
|
||||
export default Component.extend({
|
||||
actions: {
|
||||
close: function(){
|
||||
this.sendAction();
|
||||
},
|
||||
delete: function(){
|
||||
var groupId = this.get('groupId');
|
||||
let groupId = this.get('groupId');
|
||||
|
||||
Em.$.ajax(this.get('apiURL') + '/groups/' + groupId, {
|
||||
$.ajax(this.get('apiURL') + '/groups/' + groupId, {
|
||||
contentType: 'application/json',
|
||||
type: 'DELETE'
|
||||
});
|
||||
|
||||
var groupsData = this.get('groupsData'), newGroupsData = [];
|
||||
let groupsData = this.get('groupsData'), newGroupsData = [];
|
||||
for (let key in groupsData) {
|
||||
if(groupsData.hasOwnProperty(key) && groupsData[key].name !== this.get('groupName') ){
|
||||
newGroupsData[key] = groupsData[key];
|
||||
|
|
|
|||
|
|
@ -1,13 +1,73 @@
|
|||
import Em from 'ember';
|
||||
import Ember from 'ember';
|
||||
|
||||
export default Em.Component.extend({
|
||||
const {
|
||||
Component,
|
||||
observer,
|
||||
computed,
|
||||
isEmpty,
|
||||
isNone,
|
||||
} = Ember;
|
||||
|
||||
export default Component.extend({
|
||||
classNames: ['dropdown-menu'],
|
||||
elementId: 'groupList',
|
||||
|
||||
tagName: null,
|
||||
|
||||
groupIdSelection: null,
|
||||
|
||||
groupsArrData: computed('groupsData', 'groupIdSelection', function(){
|
||||
let groupsData = this.get('groupsData'), lightsData = this.get('lightsData'), groupsArrData = [], ids = [], groupIdSelection = this.get('groupIdSelection');
|
||||
|
||||
for (let key in lightsData) {
|
||||
if(lightsData.hasOwnProperty(key) && lightsData[key].state.reachable){
|
||||
ids.push(key);
|
||||
}
|
||||
}
|
||||
groupsArrData.push({name: 'All', data: {lights: ids, key: '0' }, rowClass: groupIdSelection === '0' ? 'groupRow selectedRow' : 'groupRow', deletable: false});
|
||||
|
||||
for (let key in groupsData) {
|
||||
if (groupsData.hasOwnProperty(key)) {
|
||||
let rowClass = 'groupRow';
|
||||
|
||||
if(key === groupIdSelection){
|
||||
rowClass += ' selectedRow';
|
||||
}
|
||||
|
||||
groupsArrData.push({name: groupsData[key].name, data: {lights: groupsData[key].lights, key: key}, rowClass: rowClass, deletable: true});
|
||||
}
|
||||
}
|
||||
|
||||
return groupsArrData;
|
||||
}),
|
||||
|
||||
onGroupIdSelectionChanged: observer('groupIdSelection', 'groupsArrData', function(){
|
||||
let groupIdSelection = this.get('groupIdSelection'),
|
||||
lights = [];
|
||||
|
||||
this.get('groupsArrData').some(function(group){
|
||||
if(group.data.key === groupIdSelection){
|
||||
lights = group.data.lights;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
this.get('storage').set('huegasm.selectedGroup', groupIdSelection);
|
||||
|
||||
if(!isNone(groupIdSelection) && !isEmpty(lights)){
|
||||
this.set('activeLights', lights);
|
||||
}
|
||||
}),
|
||||
|
||||
didInsertElement(){
|
||||
let selectGroup = '0',
|
||||
storageItem = this.get('storage').get('huegasm.selectedGroup');
|
||||
|
||||
if(storageItem){
|
||||
selectGroup = storageItem;
|
||||
}
|
||||
|
||||
this.set('groupIdSelection', selectGroup);
|
||||
},
|
||||
|
||||
actions: {
|
||||
selectGroup(selection){
|
||||
this.set('groupIdSelection', selection);
|
||||
|
|
@ -22,57 +82,5 @@ export default Em.Component.extend({
|
|||
toggleAddGroupsModal(){
|
||||
this.toggleProperty('isShowingAddGroupsModal');
|
||||
}
|
||||
},
|
||||
|
||||
groupsArrData: function(){
|
||||
var groupsData = this.get('groupsData'), lightsData = this.get('lightsData'), groupsArrData = [], ids = [], groupIdSelection = this.get('groupIdSelection');
|
||||
|
||||
for (let key in lightsData) {
|
||||
if(lightsData.hasOwnProperty(key) && lightsData[key].state.reachable){
|
||||
ids.push(key);
|
||||
}
|
||||
}
|
||||
groupsArrData.push({name: 'All', data: {lights: ids, key: '0' }, rowClass: groupIdSelection === '0' ? 'groupRow selectedRow' : 'groupRow', deletable: false});
|
||||
|
||||
for (let key in groupsData) {
|
||||
if (groupsData.hasOwnProperty(key)) {
|
||||
var rowClass = 'groupRow';
|
||||
|
||||
if(key === groupIdSelection){
|
||||
rowClass += ' selectedRow';
|
||||
}
|
||||
|
||||
groupsArrData.push({name: groupsData[key].name, data: {lights: groupsData[key].lights, key: key}, rowClass: rowClass, deletable: true});
|
||||
}
|
||||
}
|
||||
|
||||
return groupsArrData;
|
||||
}.property('groupsData', 'groupIdSelection'),
|
||||
|
||||
onGroupIdSelectionChanged: function(){
|
||||
var groupIdSelection = this.get('groupIdSelection'), lights = [];
|
||||
|
||||
this.get('groupsArrData').some(function(group){
|
||||
if(group.data.key === groupIdSelection){
|
||||
lights = group.data.lights;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
this.get('storage').set('huegasm.selectedGroup', groupIdSelection);
|
||||
|
||||
if(!Em.isNone(groupIdSelection) && !Em.isEmpty(lights)){
|
||||
this.set('activeLights', lights);
|
||||
}
|
||||
}.observes('groupIdSelection', 'groupsArrData'),
|
||||
|
||||
didInsertElement(){
|
||||
var selectGroup = '0', storageItem = this.get('storage').get('huegasm.selectedGroup');
|
||||
|
||||
if(storageItem){
|
||||
selectGroup = storageItem;
|
||||
}
|
||||
|
||||
this.set('groupIdSelection', selectGroup);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,27 +1,136 @@
|
|||
import Em from 'ember';
|
||||
import Ember from 'ember';
|
||||
|
||||
export default Em.Component.extend({
|
||||
const {
|
||||
Component,
|
||||
observer,
|
||||
computed,
|
||||
isEmpty,
|
||||
isNone,
|
||||
run,
|
||||
$
|
||||
} = Ember;
|
||||
|
||||
export default Component.extend({
|
||||
classNames: ['container-fluid'],
|
||||
elementId: 'hueControls',
|
||||
|
||||
bridgeIp: null,
|
||||
manualBridgeIp: null,
|
||||
bridgeUsername: null,
|
||||
|
||||
updateGroupsData: true,
|
||||
groupsData: null,
|
||||
lightsData: null,
|
||||
|
||||
activeLights: [],
|
||||
tabList: ["Lights", "Music"],
|
||||
selectedTab: 1,
|
||||
pauseLightUpdates: false,
|
||||
|
||||
lightsTabSelected: computed.equal('selectedTab', 0),
|
||||
musicTabSelected: computed.equal('selectedTab', 1),
|
||||
|
||||
dimmerOnClass: computed('dimmerOn', function(){
|
||||
return this.get('dimmerOn') ? 'dimmerOn' : null;
|
||||
}),
|
||||
|
||||
ready: computed('lightsData', 'trial', function() {
|
||||
return this.get('trial') || !isNone(this.get('lightsData'));
|
||||
}),
|
||||
|
||||
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');
|
||||
|
||||
this.get('tabList').forEach(function(tab, i){
|
||||
let selected = false;
|
||||
|
||||
if(i === selectedTab){
|
||||
selected = true;
|
||||
}
|
||||
|
||||
tabData.push({"name": tab, "selected": selected });
|
||||
});
|
||||
|
||||
return tabData;
|
||||
}),
|
||||
|
||||
didInsertElement(){
|
||||
// here's a weird way to automatically initialize bootstrap tooltips
|
||||
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) {
|
||||
run.once(this, function(){
|
||||
$('.bootstrapTooltip').tooltip();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe($('#hueControls')[0], {childList: true, subtree: true});
|
||||
},
|
||||
|
||||
init() {
|
||||
this._super();
|
||||
|
||||
if(!this.get('trial')) {
|
||||
this.doUpdateGroupsData();
|
||||
this.updateLightData();
|
||||
this.set('lightsDataIntervalHandle', setInterval(this.updateLightData.bind(this), 2000));
|
||||
}
|
||||
|
||||
if (!isNone(this.get('storage').get('huegasm.selectedTab'))) {
|
||||
this.set('selectedTab', this.get('storage').get('huegasm.selectedTab'));
|
||||
}
|
||||
},
|
||||
|
||||
onUpdateGroupsDataChange: observer('updateGroupsData', function(){
|
||||
if(this.get('updateGroupsData')){
|
||||
setTimeout(()=>{ this.doUpdateGroupsData(); }, 1000);
|
||||
}
|
||||
}),
|
||||
|
||||
doUpdateGroupsData(){
|
||||
$.get(this.get('apiURL') + '/groups', (result, status)=>{
|
||||
if (status === 'success' ) {
|
||||
this.set('groupsData', result);
|
||||
}
|
||||
});
|
||||
|
||||
this.toggleProperty('updateGroupsData');
|
||||
},
|
||||
|
||||
updateLightData(){
|
||||
let fail = ()=>{
|
||||
clearInterval(this.get('lightsDataIntervalHandle'));
|
||||
|
||||
this.get('storage').remove('huegasm.bridgeIp');
|
||||
this.get('storage').remove('huegasm.bridgeUsername');
|
||||
|
||||
location.reload();
|
||||
};
|
||||
|
||||
if(!this.get('pauseLightUpdates')){
|
||||
$.get(this.get('apiURL') + '/lights', (result, status)=>{
|
||||
if(!isNone(result[0]) && !isNone(result[0].error)){
|
||||
fail();
|
||||
} else if (status === 'success' && JSON.stringify(this.get('lightsData')) !== JSON.stringify(result)) {
|
||||
this.set('lightsData', result);
|
||||
}
|
||||
}).fail(fail);
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
changeTab(tabName){
|
||||
var index = this.get('tabList').indexOf(tabName);
|
||||
let index = this.get('tabList').indexOf(tabName);
|
||||
this.set('selectedTab', index);
|
||||
this.get('storage').set('huegasm.selectedTab', index);
|
||||
},
|
||||
clearBridge() {
|
||||
var storage = this.get('storage');
|
||||
let storage = this.get('storage');
|
||||
storage.remove('huegasm.bridgeUsername');
|
||||
storage.remove('huegasm.bridgeIp');
|
||||
location.reload();
|
||||
|
|
@ -31,10 +140,10 @@ export default Em.Component.extend({
|
|||
location.reload();
|
||||
},
|
||||
startIntro(){
|
||||
var INTRO = introJs,
|
||||
let INTRO = introJs,
|
||||
intro = INTRO(),
|
||||
playerBottom = Em.$('#playerBottom'),
|
||||
beatDetectionAreaArrowIcon = Em.$('#beatDetectionAreaArrowIcon');
|
||||
playerBottom = $('#playerBottom'),
|
||||
beatDetectionAreaArrowIcon = $('#beatDetectionAreaArrowIcon');
|
||||
|
||||
this.set('dimmerOn', false);
|
||||
|
||||
|
|
@ -88,12 +197,12 @@ export default Em.Component.extend({
|
|||
'You may toggle a light\'s state by clicking on it.'
|
||||
},
|
||||
{
|
||||
element: Em.$('.settingsItem')[0],
|
||||
element: $('.settingsItem')[0],
|
||||
intro: 'The Groups menu allows for saving and quickly selecting groups of lights.',
|
||||
position: 'left'
|
||||
},
|
||||
{
|
||||
element: Em.$('.settingsItem')[1],
|
||||
element: $('.settingsItem')[1],
|
||||
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.',
|
||||
position: 'left'
|
||||
|
|
@ -110,15 +219,15 @@ export default Em.Component.extend({
|
|||
// it's VERY ugly but it works
|
||||
intro.onchange((element) => {
|
||||
if(element.id === 'musicTab' || element.id === 'playlist' || element.id === 'playerArea' || element.id === 'beatOptionRow' || element.id === 'beatOptionButtonGroup' || element.id === 'beatContainer' || element.id === 'usingMicAudioTooltip'){
|
||||
Em.$('#musicTab').removeClass('hidden');
|
||||
Em.$('#lightsTab').addClass('hidden');
|
||||
Em.$('.navigationItem').eq(0).removeClass('active');
|
||||
Em.$('.navigationItem').eq(1).addClass('active');
|
||||
$('#musicTab').removeClass('hidden');
|
||||
$('#lightsTab').addClass('hidden');
|
||||
$('.navigationItem').eq(0).removeClass('active');
|
||||
$('.navigationItem').eq(1).addClass('active');
|
||||
} else {
|
||||
Em.$('#lightsTab').removeClass('hidden');
|
||||
Em.$('#musicTab').addClass('hidden');
|
||||
Em.$('.navigationItem').eq(1).removeClass('active');
|
||||
Em.$('.navigationItem').eq(0).addClass('active');
|
||||
$('#lightsTab').removeClass('hidden');
|
||||
$('#musicTab').addClass('hidden');
|
||||
$('.navigationItem').eq(1).removeClass('active');
|
||||
$('.navigationItem').eq(0).addClass('active');
|
||||
}
|
||||
|
||||
if(element.id === 'musicTab' || element.id === 'playlist' || element.id === 'playerArea'){
|
||||
|
|
@ -134,16 +243,16 @@ export default Em.Component.extend({
|
|||
beatDetectionAreaArrowIcon.removeClass('keyboard-arrow-down').addClass('keyboard-arrow-up');
|
||||
}
|
||||
} else if(element.id === 'dimmer'){
|
||||
Em.$(document).click();
|
||||
$(document).click();
|
||||
}
|
||||
});
|
||||
|
||||
var onFinish = ()=>{
|
||||
let onFinish = ()=>{
|
||||
this.set('activeTab', 1);
|
||||
Em.$('#musicTab').removeClass('hidden');
|
||||
Em.$('#lightsTab').addClass('hidden');
|
||||
Em.$('.navigationItem').eq(0).removeClass('active');
|
||||
Em.$('.navigationItem').eq(1).addClass('active');
|
||||
$('#musicTab').removeClass('hidden');
|
||||
$('#lightsTab').addClass('hidden');
|
||||
$('.navigationItem').eq(0).removeClass('active');
|
||||
$('.navigationItem').eq(1).addClass('active');
|
||||
|
||||
if(beatDetectionAreaArrowIcon.hasClass('keyboard-arrow-up')){
|
||||
playerBottom.show();
|
||||
|
|
@ -151,7 +260,7 @@ export default Em.Component.extend({
|
|||
playerBottom.hide();
|
||||
}
|
||||
}, onExit = ()=>{
|
||||
var dimmer = Em.$('#dimmer');
|
||||
let dimmer = $('#dimmer');
|
||||
|
||||
onFinish();
|
||||
dimmer.popover({
|
||||
|
|
@ -167,114 +276,11 @@ export default Em.Component.extend({
|
|||
|
||||
// skip hidden/missing elements
|
||||
intro.onafterchange((element)=>{
|
||||
var elem = Em.$(element);
|
||||
let elem = $(element);
|
||||
if(elem.html() === '<!---->'){
|
||||
Em.$('.introjs-nextbutton').click();
|
||||
$('.introjs-nextbutton').click();
|
||||
}
|
||||
}).onexit(onExit).oncomplete(onFinish).start();
|
||||
}
|
||||
},
|
||||
|
||||
apiURL: function(){
|
||||
return 'http://' + this.get('bridgeIp') + '/api/' + this.get('bridgeUsername');
|
||||
}.property('bridgeIp', 'bridgeUsername'),
|
||||
|
||||
didInsertElement(){
|
||||
// here's a weird way to automatically initialize bootstrap tooltips
|
||||
var observer = new MutationObserver(function(mutations) {
|
||||
var haveTooltip = !mutations.every(function(mutation) {
|
||||
return Em.isEmpty(mutation.addedNodes) || Em.isNone(mutation.addedNodes[0].classList) || mutation.addedNodes[0].classList.contains('tooltip');
|
||||
});
|
||||
|
||||
if(haveTooltip) {
|
||||
Em.run.once(this, function(){
|
||||
Em.$('.bootstrapTooltip').tooltip();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(Em.$('#hueControls')[0], {childList: true, subtree: true});
|
||||
},
|
||||
|
||||
init() {
|
||||
this._super();
|
||||
|
||||
if(!this.get('trial')) {
|
||||
this.doUpdateGroupsData();
|
||||
this.updateLightData();
|
||||
this.set('lightsDataIntervalHandle', setInterval(this.updateLightData.bind(this), 2000));
|
||||
}
|
||||
|
||||
if (!Em.isNone(this.get('storage').get('huegasm.selectedTab'))) {
|
||||
this.set('selectedTab', this.get('storage').get('huegasm.selectedTab'));
|
||||
}
|
||||
},
|
||||
|
||||
onUpdateGroupsDataChange: function(){
|
||||
if(this.get('updateGroupsData')){
|
||||
setTimeout(()=>{ this.doUpdateGroupsData(); }, 1000);
|
||||
}
|
||||
}.observes('updateGroupsData'),
|
||||
|
||||
doUpdateGroupsData(){
|
||||
Em.$.get(this.get('apiURL') + '/groups', (result, status)=>{
|
||||
if (status === 'success' ) {
|
||||
this.set('groupsData', result);
|
||||
}
|
||||
});
|
||||
|
||||
this.toggleProperty('updateGroupsData');
|
||||
},
|
||||
|
||||
tabList: ["Lights", "Music"],
|
||||
selectedTab: 1,
|
||||
tabData: function(){
|
||||
var tabData = [], selectedTab = this.get('selectedTab');
|
||||
|
||||
this.get('tabList').forEach(function(tab, i){
|
||||
var selected = false;
|
||||
|
||||
if(i === selectedTab){
|
||||
selected = true;
|
||||
}
|
||||
|
||||
tabData.push({"name": tab, "selected": selected });
|
||||
});
|
||||
|
||||
return tabData;
|
||||
}.property('tabList', 'selectedTab'),
|
||||
|
||||
lightsTabSelected: Em.computed.equal('selectedTab', 0),
|
||||
musicTabSelected: Em.computed.equal('selectedTab', 1),
|
||||
|
||||
pauseLightUpdates: false,
|
||||
|
||||
updateLightData(){
|
||||
var fail = ()=>{
|
||||
clearInterval(this.get('lightsDataIntervalHandle'));
|
||||
|
||||
this.get('storage').remove('huegasm.bridgeIp');
|
||||
this.get('storage').remove('huegasm.bridgeUsername');
|
||||
|
||||
location.reload();
|
||||
};
|
||||
|
||||
if(!this.get('pauseLightUpdates')){
|
||||
Em.$.get(this.get('apiURL') + '/lights', (result, status)=>{
|
||||
if(!Em.isNone(result[0]) && !Em.isNone(result[0].error)){
|
||||
fail();
|
||||
} else if (status === 'success' && JSON.stringify(this.get('lightsData')) !== JSON.stringify(result)) {
|
||||
this.set('lightsData', result);
|
||||
}
|
||||
}).fail(fail);
|
||||
}
|
||||
},
|
||||
|
||||
dimmerOnClass: function(){
|
||||
return this.get('dimmerOn') ? 'dimmerOn' : null;
|
||||
}.property('dimmerOn'),
|
||||
|
||||
ready: function() {
|
||||
return this.get('trial') || !Em.isNone(this.get('lightsData'));
|
||||
}.property('lightsData', 'trial')
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,56 +1,55 @@
|
|||
import Em from 'ember';
|
||||
import Ember from 'ember';
|
||||
|
||||
export default Em.Component.extend({
|
||||
actions: {
|
||||
toggleDimmer(){
|
||||
this.toggleProperty('dimmerOn');
|
||||
},
|
||||
isReady(){
|
||||
this.set('ready', true);
|
||||
}
|
||||
},
|
||||
const {
|
||||
Component,
|
||||
computed,
|
||||
isEmpty,
|
||||
isNone,
|
||||
$
|
||||
} = Ember;
|
||||
|
||||
export default Component.extend({
|
||||
bridgeIp: null,
|
||||
|
||||
bridgeUsername: null,
|
||||
|
||||
trial: false,
|
||||
|
||||
storage: null,
|
||||
|
||||
dimmerOn: false,
|
||||
|
||||
ready: false,
|
||||
|
||||
dimmerOnClass: function () {
|
||||
var dimmerOn = this.get('dimmerOn'),
|
||||
year: computed(function(){
|
||||
return new Date().getFullYear();
|
||||
}),
|
||||
|
||||
dimmerOnClass: computed('dimmerOn', function(){
|
||||
let dimmerOn = this.get('dimmerOn'),
|
||||
storage = this.get('storage'),
|
||||
dimmerOnClass = null;
|
||||
|
||||
if (dimmerOn) {
|
||||
Em.$('body').addClass('dimmerOn');
|
||||
Em.$('html').addClass('dimmerOn');
|
||||
$('body').addClass('dimmerOn');
|
||||
$('html').addClass('dimmerOn');
|
||||
dimmerOnClass = 'active';
|
||||
} else {
|
||||
Em.$('body').removeClass('dimmerOn');
|
||||
Em.$('html').removeClass('dimmerOn');
|
||||
$('body').removeClass('dimmerOn');
|
||||
$('html').removeClass('dimmerOn');
|
||||
}
|
||||
|
||||
storage.set('huegasm.dimmerOn', dimmerOn);
|
||||
|
||||
return dimmerOnClass;
|
||||
}.property('dimmerOn'),
|
||||
}),
|
||||
|
||||
init(){
|
||||
this._super();
|
||||
|
||||
var storage = new window.Locally.Store({compress: true});
|
||||
let storage = new window.Locally.Store({compress: true});
|
||||
this.set('storage', storage);
|
||||
|
||||
if (!Em.isNone(storage.get('huegasm.dimmerOn'))) {
|
||||
if (!isNone(storage.get('huegasm.dimmerOn'))) {
|
||||
this.set('dimmerOn', storage.get('huegasm.dimmerOn'));
|
||||
}
|
||||
|
||||
if (!Em.isEmpty(storage.get('huegasm.bridgeIp')) && !Em.isEmpty(storage.get('huegasm.bridgeUsername'))) {
|
||||
if (!isEmpty(storage.get('huegasm.bridgeIp')) && !isEmpty(storage.get('huegasm.bridgeUsername'))) {
|
||||
this.setProperties({
|
||||
bridgeIp: storage.get('huegasm.bridgeIp'),
|
||||
bridgeUsername: storage.get('huegasm.bridgeUsername')
|
||||
|
|
@ -58,7 +57,12 @@ export default Em.Component.extend({
|
|||
}
|
||||
},
|
||||
|
||||
year: function () {
|
||||
return new Date().getFullYear();
|
||||
}.property()
|
||||
actions: {
|
||||
toggleDimmer(){
|
||||
this.toggleProperty('dimmerOn');
|
||||
},
|
||||
isReady(){
|
||||
this.set('ready', true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,73 +1,26 @@
|
|||
import Em from 'ember';
|
||||
import Ember from 'ember';
|
||||
|
||||
export default Em.Component.extend({
|
||||
const {
|
||||
Component,
|
||||
observer,
|
||||
isEmpty,
|
||||
$,
|
||||
A
|
||||
} = Ember;
|
||||
|
||||
export default Component.extend({
|
||||
classNames: ['lightGroup'],
|
||||
|
||||
isHovering: false,
|
||||
|
||||
lightsList: Em.A(),
|
||||
|
||||
actions: {
|
||||
clickLight(id, data){
|
||||
var light = Em.$('.light'+id);
|
||||
|
||||
if(!light.hasClass('bootstrapTooltip')){
|
||||
light = light.parent();
|
||||
}
|
||||
|
||||
if(light.hasClass('lightInactive')){
|
||||
light.addClass('lightActive').removeClass('lightInactive');
|
||||
} else if(light.hasClass('lightActive')){
|
||||
light.addClass('lightInactive').removeClass('lightActive');
|
||||
}
|
||||
|
||||
this.sendAction('action', id, data);
|
||||
},
|
||||
lightStartHover(id){
|
||||
var hoveredLight = this.get('lightsList').filter(function(light){
|
||||
return light.activeClass !== 'unreachable' && light.id === id[0];
|
||||
});
|
||||
|
||||
if(!Em.isEmpty(hoveredLight) && this.get('noHover') !== true){
|
||||
Em.$.ajax(this.get('apiURL') + '/lights/' + id + '/state', {
|
||||
data: JSON.stringify({"alert": "lselect"}),
|
||||
contentType: 'application/json',
|
||||
type: 'PUT'
|
||||
});
|
||||
}
|
||||
|
||||
this.set('isHovering', true);
|
||||
},
|
||||
lightStopHover(id){
|
||||
var hoveredLight = this.get('lightsList').filter(function(light){
|
||||
return light.activeClass !== 'unreachable' && light.id === id[0];
|
||||
});
|
||||
|
||||
if(!Em.isEmpty(hoveredLight) && this.get('noHover') !== true){
|
||||
Em.$.ajax(this.get('apiURL') + '/lights/' + id + '/state', {
|
||||
data: JSON.stringify({"alert": "none"}),
|
||||
contentType: 'application/json',
|
||||
type: 'PUT'
|
||||
});
|
||||
}
|
||||
|
||||
this.set('isHovering', false);
|
||||
this.onLightsDataChange();
|
||||
}
|
||||
},
|
||||
|
||||
didInsertElement() {
|
||||
if(this.get('lightsData')){
|
||||
this.onLightsDataChange();
|
||||
}
|
||||
},
|
||||
lightsList: A(),
|
||||
|
||||
// list of all the lights in the hue system
|
||||
onLightsDataChange: function(){
|
||||
onLightsDataChange: observer('lightsData', 'activeLights.[]', 'dimmerOn', function(){
|
||||
if(!this.get('isHovering')){
|
||||
var lightsData = this.get('lightsData'), lightsList = Em.A(), type;
|
||||
for (var key in lightsData) {
|
||||
let lightsData = this.get('lightsData'),
|
||||
lightsList = A(),
|
||||
type;
|
||||
|
||||
for (let key in lightsData) {
|
||||
if (lightsData.hasOwnProperty(key) && lightsData[key].state.reachable) {
|
||||
switch(lightsData[key].modelid){
|
||||
case 'LCT001':
|
||||
|
|
@ -110,7 +63,7 @@ export default Em.Component.extend({
|
|||
type = 'a19';
|
||||
}
|
||||
|
||||
var activeClass = 'lightActive';
|
||||
let activeClass = 'lightActive';
|
||||
|
||||
if(!this.get('activeLights').contains(key)){
|
||||
activeClass = 'lightInactive';
|
||||
|
|
@ -122,5 +75,60 @@ export default Em.Component.extend({
|
|||
|
||||
this.set('lightsList', lightsList);
|
||||
}
|
||||
}.observes('lightsData', 'activeLights.[]', 'dimmerOn')
|
||||
}),
|
||||
|
||||
didInsertElement() {
|
||||
if(this.get('lightsData')){
|
||||
this.onLightsDataChange();
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
clickLight(id, data){
|
||||
let light = $('.light'+id);
|
||||
|
||||
if(!light.hasClass('bootstrapTooltip')){
|
||||
light = light.parent();
|
||||
}
|
||||
|
||||
if(light.hasClass('lightInactive')){
|
||||
light.addClass('lightActive').removeClass('lightInactive');
|
||||
} else if(light.hasClass('lightActive')){
|
||||
light.addClass('lightInactive').removeClass('lightActive');
|
||||
}
|
||||
|
||||
this.sendAction('action', id, data);
|
||||
},
|
||||
lightStartHover(id){
|
||||
let hoveredLight = this.get('lightsList').filter(function(light){
|
||||
return light.activeClass !== 'unreachable' && light.id === id[0];
|
||||
});
|
||||
|
||||
if(!isEmpty(hoveredLight) && this.get('noHover') !== true){
|
||||
$.ajax(this.get('apiURL') + '/lights/' + id + '/state', {
|
||||
data: JSON.stringify({"alert": "lselect"}),
|
||||
contentType: 'application/json',
|
||||
type: 'PUT'
|
||||
});
|
||||
}
|
||||
|
||||
this.set('isHovering', true);
|
||||
},
|
||||
lightStopHover(id){
|
||||
let hoveredLight = this.get('lightsList').filter(function(light){
|
||||
return light.activeClass !== 'unreachable' && light.id === id[0];
|
||||
});
|
||||
|
||||
if(!isEmpty(hoveredLight) && this.get('noHover') !== true){
|
||||
$.ajax(this.get('apiURL') + '/lights/' + id + '/state', {
|
||||
data: JSON.stringify({"alert": "none"}),
|
||||
contentType: 'application/json',
|
||||
type: 'PUT'
|
||||
});
|
||||
}
|
||||
|
||||
this.set('isHovering', false);
|
||||
this.onLightsDataChange();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,13 @@
|
|||
import Em from 'ember';
|
||||
import Ember from 'ember';
|
||||
|
||||
export default Em.Component.extend({
|
||||
const {
|
||||
Component,
|
||||
observer,
|
||||
computed,
|
||||
$
|
||||
} = Ember;
|
||||
|
||||
export default Component.extend({
|
||||
classNames: ['col-sm-8', 'col-sm-offset-2', 'col-xs-12'],
|
||||
classNameBindings: ['active::hidden'],
|
||||
elementId: 'lightsTab',
|
||||
|
|
@ -12,9 +19,150 @@ export default Em.Component.extend({
|
|||
|
||||
colorPickerDisplayed: false,
|
||||
|
||||
rgb: [255, 255, 255],
|
||||
|
||||
lightsOn: false,
|
||||
|
||||
// COLOR LOOP related stuff
|
||||
colorLoopOn: false,
|
||||
|
||||
lightsOnTxt: computed('lightsOn', function(){
|
||||
return this.get('lightsOn') ? 'On' : 'Off';
|
||||
}),
|
||||
|
||||
colorloopOnTxt: computed('colorLoopOn', function(){
|
||||
return this.get('colorLoopOn') ? 'On' : 'Off';
|
||||
}),
|
||||
|
||||
colorRowAction: computed('strobeOn', function() {
|
||||
if (this.get('trial')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return 'toggleColorpicker';
|
||||
}),
|
||||
|
||||
// determines the average brightness of the hue system for the brightness slider
|
||||
lightsBrightness: computed('lightsData', function(){
|
||||
let lightsData = this.get('lightsData'), activeLights = this.get('activeLights'), lightsBrightness = 0;
|
||||
|
||||
activeLights.forEach(function(light){
|
||||
lightsBrightness += lightsData[light].state.bri;
|
||||
});
|
||||
|
||||
return lightsBrightness/activeLights.length;
|
||||
}),
|
||||
|
||||
brightnessControlDisabled: computed.not('lightsOn'),
|
||||
|
||||
onColorLoopOnChange: observer('colorLoopOn', function(){
|
||||
let lightsData = this.get('lightsData'),
|
||||
activeLights = this.get('activeLights'),
|
||||
colorLoopsOn = this.get('colorLoopOn'),
|
||||
effect = colorLoopsOn ? 'colorloop' : 'none';
|
||||
|
||||
let colorLoopsOnSystem = activeLights.some(function(light) {
|
||||
return lightsData[light].state.effect === 'colorloop';
|
||||
});
|
||||
|
||||
// if the internal lights state is different than the one from lightsData ( user manually toggled the switch ), send the request to change the bulbs state
|
||||
if(colorLoopsOn !== colorLoopsOnSystem){
|
||||
activeLights.forEach((light)=>{
|
||||
if(this.get('lightsData')[light].state.effect !== effect) {
|
||||
$.ajax(this.get('apiURL') + '/lights/' + light + '/state', {
|
||||
data: JSON.stringify({'effect': effect }),
|
||||
contentType: 'application/json',
|
||||
type: 'PUT'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}),
|
||||
|
||||
rgbPreview: observer('rgb', function() {
|
||||
let rgb = this.get('rgb'),
|
||||
xy = this.rgbToXy(rgb[0], rgb[1], rgb[2]);
|
||||
|
||||
this.set('colorLoopOn', false);
|
||||
|
||||
this.get('activeLights').forEach((light) => {
|
||||
$.ajax(this.get('apiURL') + '/lights/' + light + '/state', {
|
||||
data: JSON.stringify({"xy": xy}),
|
||||
contentType: 'application/json',
|
||||
type: 'PUT'
|
||||
});
|
||||
});
|
||||
|
||||
this.set('colorLoopOn', false);
|
||||
$('.color').css('background', 'rgb(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ')');
|
||||
}),
|
||||
|
||||
// determines whether the lights are on/off for the lights switch
|
||||
lightsOnChange: observer('lightsData.@each.state.on', 'activeLights.[]', function(){
|
||||
if(!this.get('strobeOn')){
|
||||
let lightsData = this.get('lightsData'), lightsOn = this.get('activeLights').some(function(light) {
|
||||
return lightsData[light].state.on === true;
|
||||
});
|
||||
|
||||
this.set('lightsOn', lightsOn);
|
||||
}
|
||||
}),
|
||||
|
||||
onLightsOnChange: observer('lightsOn', function(){
|
||||
let lightsData = this.get('lightsData'), activeLights = this.get('activeLights'), lightsOn = this.get('lightsOn'), self = this;
|
||||
|
||||
let lightsOnSystem = activeLights.some(function(light) {
|
||||
return lightsData[light].state.on === true;
|
||||
});
|
||||
|
||||
// if the internal lights state is different than the one from lightsData ( user manually toggled the switch ), send the request to change the bulbs state
|
||||
if(lightsOn !== lightsOnSystem){
|
||||
activeLights.forEach(function (light) {
|
||||
$.ajax(self.get('apiURL') + '/lights/' + light + '/state', {
|
||||
data: JSON.stringify({"on": lightsOn}),
|
||||
contentType: 'application/json',
|
||||
type: 'PUT'
|
||||
});
|
||||
});
|
||||
}
|
||||
}),
|
||||
|
||||
onBrightnessChanged: observer('lightsBrightness', function(){
|
||||
let lightsData = this.get('lightsData'), lightsBrightnessSystem = false, lightsBrightness = this.get('lightsBrightness'), activeLights = this.get('activeLights'), self = this;
|
||||
|
||||
activeLights.forEach(function(light){
|
||||
lightsBrightnessSystem += lightsData[light].state.bri;
|
||||
});
|
||||
|
||||
lightsBrightnessSystem /= activeLights.length;
|
||||
|
||||
// if the internal lights state is different than the one from lightsData ( user manually toggled the switch ), send the request to change the bulbs state
|
||||
if(lightsBrightness !== lightsBrightnessSystem){
|
||||
activeLights.forEach(function(light){
|
||||
$.ajax(self.get('apiURL') + '/lights/' + light + '/state', {
|
||||
data: JSON.stringify({"bri": lightsBrightness}),
|
||||
contentType: 'application/json',
|
||||
type: 'PUT'
|
||||
});
|
||||
});
|
||||
}
|
||||
}),
|
||||
|
||||
didInsertElement() {
|
||||
$(document).click((event)=>{
|
||||
if(this.get('colorPickerDisplayed') && !event.target.classList.contains('color') && !$(event.target).closest('.colorpicker, #colorRow').length) {
|
||||
this.toggleProperty('colorPickerDisplayed');
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('click', '#colorRow', () => {
|
||||
this.send('toggleColorpicker');
|
||||
});
|
||||
},
|
||||
|
||||
actions: {
|
||||
clickLight(light){
|
||||
var activeLights = this.get('activeLights'),
|
||||
let activeLights = this.get('activeLights'),
|
||||
lightId = activeLights.indexOf(light);
|
||||
|
||||
if(lightId !== -1){
|
||||
|
|
@ -23,7 +171,7 @@ export default Em.Component.extend({
|
|||
activeLights.pushObject(light);
|
||||
|
||||
// sync the current light settings to the newly added light
|
||||
var options = {on: this.get('lightsOn'), bri: this.get('lightsBrightness'), effect: this.get('colorLoopOn') ? 'colorloop' : 'none'},
|
||||
let options = {on: this.get('lightsOn'), bri: this.get('lightsBrightness'), effect: this.get('colorLoopOn') ? 'colorloop' : 'none'},
|
||||
rgb = this.get('rgb');
|
||||
|
||||
if(rgb[0] !== 255 && rgb[1] !== 255 && rgb[2] !== 255) {
|
||||
|
|
@ -32,7 +180,7 @@ export default Em.Component.extend({
|
|||
|
||||
options['transitiontime'] = 0;
|
||||
|
||||
Em.$.ajax(this.get('apiURL') + '/lights/' + light + '/state', {
|
||||
$.ajax(this.get('apiURL') + '/lights/' + light + '/state', {
|
||||
data: JSON.stringify(options),
|
||||
contentType: 'application/json',
|
||||
type: 'PUT'
|
||||
|
|
@ -44,146 +192,6 @@ export default Em.Component.extend({
|
|||
}
|
||||
},
|
||||
|
||||
didInsertElement() {
|
||||
Em.$(document).click((event)=>{
|
||||
if(this.get('colorPickerDisplayed') && !event.target.classList.contains('color') && !Em.$(event.target).closest('.colorpicker, #colorRow').length) {
|
||||
this.toggleProperty('colorPickerDisplayed');
|
||||
}
|
||||
});
|
||||
|
||||
Em.$(document).on('click', '#colorRow', () => {
|
||||
this.send('toggleColorpicker');
|
||||
});
|
||||
},
|
||||
|
||||
rgb: [255, 255, 255],
|
||||
rgbPreview: function() {
|
||||
var rgb = this.get('rgb'),
|
||||
xy = this.rgbToXy(rgb[0], rgb[1], rgb[2]);
|
||||
|
||||
this.set('colorLoopOn', false);
|
||||
|
||||
this.get('activeLights').forEach((light) => {
|
||||
Em.$.ajax(this.get('apiURL') + '/lights/' + light + '/state', {
|
||||
data: JSON.stringify({"xy": xy}),
|
||||
contentType: 'application/json',
|
||||
type: 'PUT'
|
||||
});
|
||||
});
|
||||
|
||||
this.set('colorLoopOn', false);
|
||||
Em.$('.color').css('background', 'rgb(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ')');
|
||||
}.observes('rgb'),
|
||||
|
||||
colorRowAction: function() {
|
||||
if (this.get('trial')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return 'toggleColorpicker';
|
||||
}.property('trial'),
|
||||
|
||||
// COLOR LOOP related stuff
|
||||
colorLoopOn: false,
|
||||
|
||||
onColorLoopOnChange: function(){
|
||||
var lightsData = this.get('lightsData'),
|
||||
activeLights = this.get('activeLights'),
|
||||
colorLoopsOn = this.get('colorLoopOn'),
|
||||
effect = colorLoopsOn ? 'colorloop' : 'none';
|
||||
|
||||
var colorLoopsOnSystem = activeLights.some(function(light) {
|
||||
return lightsData[light].state.effect === 'colorloop';
|
||||
});
|
||||
|
||||
// if the internal lights state is different than the one from lightsData ( user manually toggled the switch ), send the request to change the bulbs state
|
||||
if(colorLoopsOn !== colorLoopsOnSystem){
|
||||
activeLights.forEach((light)=>{
|
||||
if(this.get('lightsData')[light].state.effect !== effect) {
|
||||
Em.$.ajax(this.get('apiURL') + '/lights/' + light + '/state', {
|
||||
data: JSON.stringify({'effect': effect }),
|
||||
contentType: 'application/json',
|
||||
type: 'PUT'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}.observes('colorLoopOn'),
|
||||
|
||||
lightsOn: false,
|
||||
|
||||
// determines whether the lights are on/off for the lights switch
|
||||
lightsOnCHange: function(){
|
||||
if(!this.get('strobeOn')){
|
||||
var lightsData = this.get('lightsData'), lightsOn = this.get('activeLights').some(function(light) {
|
||||
return lightsData[light].state.on === true;
|
||||
});
|
||||
|
||||
this.set('lightsOn', lightsOn);
|
||||
}
|
||||
}.observes('lightsData.@each.state.on', 'activeLights.[]'),
|
||||
|
||||
// determines the average brightness of the hue system for the brightness slider
|
||||
lightsBrightness: function(){
|
||||
var lightsData = this.get('lightsData'), activeLights = this.get('activeLights'), lightsBrightness = 0;
|
||||
|
||||
activeLights.forEach(function(light){
|
||||
lightsBrightness += lightsData[light].state.bri;
|
||||
});
|
||||
|
||||
return lightsBrightness/activeLights.length;
|
||||
}.property('lightsData'),
|
||||
|
||||
brightnessControlDisabled: Em.computed.not('lightsOn'),
|
||||
|
||||
onLightsOnChange: function(){
|
||||
var lightsData = this.get('lightsData'), activeLights = this.get('activeLights'), lightsOn = this.get('lightsOn'), self = this;
|
||||
|
||||
var lightsOnSystem = activeLights.some(function(light) {
|
||||
return lightsData[light].state.on === true;
|
||||
});
|
||||
|
||||
// if the internal lights state is different than the one from lightsData ( user manually toggled the switch ), send the request to change the bulbs state
|
||||
if(lightsOn !== lightsOnSystem){
|
||||
activeLights.forEach(function (light) {
|
||||
Em.$.ajax(self.get('apiURL') + '/lights/' + light + '/state', {
|
||||
data: JSON.stringify({"on": lightsOn}),
|
||||
contentType: 'application/json',
|
||||
type: 'PUT'
|
||||
});
|
||||
});
|
||||
}
|
||||
}.observes('lightsOn'),
|
||||
|
||||
onBrightnessChanged: function(){
|
||||
var lightsData = this.get('lightsData'), lightsBrightnessSystem = false, lightsBrightness = this.get('lightsBrightness'), activeLights = this.get('activeLights'), self = this;
|
||||
|
||||
activeLights.forEach(function(light){
|
||||
lightsBrightnessSystem += lightsData[light].state.bri;
|
||||
});
|
||||
|
||||
lightsBrightnessSystem /= activeLights.length;
|
||||
|
||||
// if the internal lights state is different than the one from lightsData ( user manually toggled the switch ), send the request to change the bulbs state
|
||||
if(lightsBrightness !== lightsBrightnessSystem){
|
||||
activeLights.forEach(function(light){
|
||||
Em.$.ajax(self.get('apiURL') + '/lights/' + light + '/state', {
|
||||
data: JSON.stringify({"bri": lightsBrightness}),
|
||||
contentType: 'application/json',
|
||||
type: 'PUT'
|
||||
});
|
||||
});
|
||||
}
|
||||
}.observes('lightsBrightness'),
|
||||
|
||||
lightsOnTxt: function(){
|
||||
return this.get('lightsOn') ? 'On' : 'Off';
|
||||
}.property('lightsOn'),
|
||||
|
||||
colorloopOnTxt: function(){
|
||||
return this.get('colorLoopOn') ? 'On' : 'Off';
|
||||
}.property('colorLoopOn'),
|
||||
|
||||
// **************** STROBE LIGHT START ****************
|
||||
|
||||
strobeOn: false,
|
||||
|
|
@ -193,12 +201,12 @@ export default Em.Component.extend({
|
|||
preStrobeOnLightsDataCache: null,
|
||||
lastStrobeLight: 0,
|
||||
|
||||
onStrobeOnChange: function () {
|
||||
var lightsData = this.get('lightsData'), self = this;
|
||||
onStrobeOnChange: observer('strobeOn', function () {
|
||||
let lightsData = this.get('lightsData'), self = this;
|
||||
|
||||
if (this.get('strobeOn')) {
|
||||
this.set('preStrobeOnLightsDataCache', lightsData);
|
||||
var stobeInitRequestData = {'sat': this.get('strobeSat'), 'transitiontime': 0};
|
||||
let stobeInitRequestData = {'sat': this.get('strobeSat'), 'transitiontime': 0};
|
||||
|
||||
for (let key in lightsData) {
|
||||
if (lightsData.hasOwnProperty(key)) {
|
||||
|
|
@ -206,7 +214,7 @@ export default Em.Component.extend({
|
|||
stobeInitRequestData.on = false;
|
||||
}
|
||||
|
||||
Em.$.ajax(this.get('apiURL') + '/lights/' + key + '/state', {
|
||||
$.ajax(this.get('apiURL') + '/lights/' + key + '/state', {
|
||||
data: JSON.stringify(stobeInitRequestData),
|
||||
contentType: 'application/json',
|
||||
type: 'PUT'
|
||||
|
|
@ -216,8 +224,8 @@ export default Em.Component.extend({
|
|||
|
||||
this.set('strobeOnInervalHandle', setInterval(this.strobeStep.bind(this), 200));
|
||||
} else { // revert the light system to pre-strobe
|
||||
var preStrobeOnLightsDataCache = this.get('preStrobeOnLightsDataCache'), updateLight = function (lightIndx) {
|
||||
Em.$.ajax(self.get('apiURL') + '/lights/' + lightIndx + '/state', {
|
||||
let preStrobeOnLightsDataCache = this.get('preStrobeOnLightsDataCache'), updateLight = function (lightIndx) {
|
||||
$.ajax(self.get('apiURL') + '/lights/' + lightIndx + '/state', {
|
||||
data: JSON.stringify({
|
||||
'on': preStrobeOnLightsDataCache[lightIndx].state.on,
|
||||
'sat': preStrobeOnLightsDataCache[lightIndx].state.sat
|
||||
|
|
@ -236,10 +244,10 @@ export default Em.Component.extend({
|
|||
setTimeout(()=>{this.onColorLoopOnChange();}, 2000);
|
||||
clearInterval(this.get('strobeOnInervalHandle'));
|
||||
}
|
||||
}.observes('strobeOn'),
|
||||
}),
|
||||
|
||||
strobeStep() {
|
||||
var lastStrobeLight = (this.get('lastStrobeLight') + 1) % (this.get('activeLights').length + 1),
|
||||
let lastStrobeLight = (this.get('lastStrobeLight') + 1) % (this.get('activeLights').length + 1),
|
||||
turnOnOptions = {'on': true, 'transitiontime': 0, 'alert': 'select'};
|
||||
|
||||
// random light if in cololoop mode
|
||||
|
|
@ -247,12 +255,12 @@ export default Em.Component.extend({
|
|||
turnOnOptions.hue = Math.floor(Math.random() * 65535);
|
||||
}
|
||||
|
||||
Em.$.ajax(this.get('apiURL') + '/lights/' + lastStrobeLight + '/state', {
|
||||
$.ajax(this.get('apiURL') + '/lights/' + lastStrobeLight + '/state', {
|
||||
data: JSON.stringify(turnOnOptions),
|
||||
contentType: 'application/json',
|
||||
type: 'PUT'
|
||||
});
|
||||
Em.$.ajax(this.get('apiURL') + '/lights/' + lastStrobeLight + '/state', {
|
||||
$.ajax(this.get('apiURL') + '/lights/' + lastStrobeLight + '/state', {
|
||||
data: JSON.stringify({'on': false, 'transitiontime': 0}),
|
||||
contentType: 'application/json',
|
||||
type: 'PUT'
|
||||
|
|
@ -261,18 +269,18 @@ export default Em.Component.extend({
|
|||
this.set('lastStrobeLight', lastStrobeLight);
|
||||
},
|
||||
|
||||
strobeOnTxt: function () {
|
||||
strobeOnTxt: computed('strobeOn', function () {
|
||||
return this.get('strobeOn') ? 'On' : 'Off';
|
||||
}.property('strobeOn'),
|
||||
}),
|
||||
|
||||
dimmerOnClass: function(){
|
||||
dimmerOnClass: computed('dimmerOn', function(){
|
||||
return this.get('dimmerOn') ? 'dimmerOn' : null;
|
||||
}.property('dimmerOn'),
|
||||
}),
|
||||
|
||||
// **************** STROBE LIGHT FINISH ****************
|
||||
// http://www.developers.meethue.com/documentation/color-conversions-rgb-xy
|
||||
rgbToXy(red, green, blue){
|
||||
var X, Y, Z, x, y;
|
||||
let X, Y, Z, x, y;
|
||||
|
||||
// normalize
|
||||
red = Number((red/255));
|
||||
|
|
@ -296,7 +304,7 @@ export default Em.Component.extend({
|
|||
},
|
||||
|
||||
xyToRgb(x, y){
|
||||
var r, g, b, X, Y = 1.0, Z;
|
||||
let r, g, b, X, Y = 1.0, Z;
|
||||
|
||||
X = (Y / y) * x;
|
||||
Z = (Y / y) * (1 - x - y);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,13 +1,24 @@
|
|||
import Em from 'ember';
|
||||
import Ember from 'ember';
|
||||
|
||||
export default Em.Mixin.create({
|
||||
const {
|
||||
Mixin,
|
||||
observer,
|
||||
computed,
|
||||
isNone,
|
||||
$,
|
||||
inject,
|
||||
on,
|
||||
A
|
||||
} = Ember;
|
||||
|
||||
export default Mixin.create({
|
||||
classNames: ['col-sm-10', 'col-sm-offset-1', 'col-xs-12'],
|
||||
classNameBindings: ['active::hidden'],
|
||||
elementId: 'musicTab',
|
||||
|
||||
dancer: null,
|
||||
|
||||
notify: Em.inject.service('notify'),
|
||||
notify: inject.service('notify'),
|
||||
|
||||
beatOptions: {
|
||||
threshold: {
|
||||
|
|
@ -80,16 +91,16 @@ export default Em.Mixin.create({
|
|||
oldThreshold: null,
|
||||
|
||||
playQueuePointer: -1,
|
||||
playQueue: Em.A(),
|
||||
playQueue: A(),
|
||||
timeElapsed: 0,
|
||||
timeTotal: 0,
|
||||
lastLightBopIndex: 0,
|
||||
|
||||
usingMicSupported: false,
|
||||
|
||||
// 0 - local, 1 - mic, possibly more to come
|
||||
audioMode: 0,
|
||||
usingLocalAudio: Em.computed.equal('audioMode', 0),
|
||||
usingMicAudio: Em.computed.equal('audioMode', 1),
|
||||
usingLocalAudio: computed.equal('audioMode', 0),
|
||||
usingMicAudio: computed.equal('audioMode', 1),
|
||||
|
||||
playerBottomDisplayed: false,
|
||||
dragging: false,
|
||||
|
|
@ -104,52 +115,6 @@ export default Em.Mixin.create({
|
|||
ambienceMode: false,
|
||||
flashingTransitions: false,
|
||||
|
||||
SC_CLIENT_ID: 'aeec0034f58ecd85c2bd1deaecc41594',
|
||||
notFoundHtml: '<div class="alert alert-danger" role="alert">A microphone was not found.</div>',
|
||||
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">HERE</a>.</div>',
|
||||
notStreamableHtml(fileNames){
|
||||
var 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;
|
||||
},
|
||||
urlNotFoundHtml(url){
|
||||
return '<div class="alert alert-danger" role="alert">The URL ( ' + url + ' ) could not be resolved.</div>';
|
||||
},
|
||||
failedToPlayFileHtml(fileName){
|
||||
return '<div class="alert alert-danger" role="alert">Failed to play file ( ' + fileName + ' ).</div>';
|
||||
},
|
||||
failedToDecodeFileHtml(fileName){
|
||||
return '<div class="alert alert-danger" role="alert">Failed to decode file ( ' + fileName + ' ).</div>';
|
||||
},
|
||||
|
||||
scUrl: function(){
|
||||
var rtn = null,
|
||||
currentSong = this.get('playQueue')[this.get('playQueuePointer')];
|
||||
|
||||
if(currentSong && currentSong.scUrl && !this.get('usingMicAudio')){
|
||||
rtn = currentSong.scUrl;
|
||||
}
|
||||
|
||||
return rtn;
|
||||
}.property('playQueuePointer', 'playQueue.[]', 'usingMicAudio'),
|
||||
|
||||
playQueueEmpty: Em.computed.empty('playQueue'),
|
||||
playQueueNotEmpty: Em.computed.notEmpty('playQueue'),
|
||||
playQueueMultiple: function(){
|
||||
return this.get('playQueue').length > 1;
|
||||
}.property('playQueue.[]'),
|
||||
|
||||
seekPosition: function() {
|
||||
var timeTotal = this.get('timeTotal'), timeElapsed = this.get('timeElapsed');
|
||||
|
||||
if (timeTotal === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return timeElapsed/timeTotal*100;
|
||||
}.property('timeElapsed', 'timeTotal'),
|
||||
|
||||
// 0 - no repeat, 1 - repeat all, 2 - repeat one
|
||||
repeat: 0,
|
||||
shuffle: false,
|
||||
|
|
@ -171,15 +136,65 @@ export default Em.Mixin.create({
|
|||
soundCloudFuckUps: 0,
|
||||
maxSoundCloudFuckUps: 3,
|
||||
|
||||
largeArtworkPic: function(){
|
||||
var pic = null,
|
||||
// used to insure that we don't replay the same thing multiple times in shuffle mode
|
||||
shufflePlayed: [],
|
||||
|
||||
SC_CLIENT_ID: 'aeec0034f58ecd85c2bd1deaecc41594',
|
||||
notFoundHtml: '<div class="alert alert-danger" role="alert">A microphone was not found.</div>',
|
||||
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">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>';
|
||||
|
||||
return html;
|
||||
},
|
||||
urlNotFoundHtml(url){
|
||||
return '<div class="alert alert-danger" role="alert">The URL ( ' + url + ' ) could not be resolved.</div>';
|
||||
},
|
||||
failedToPlayFileHtml(fileName){
|
||||
return '<div class="alert alert-danger" role="alert">Failed to play file ( ' + fileName + ' ).</div>';
|
||||
},
|
||||
failedToDecodeFileHtml(fileName){
|
||||
return '<div class="alert alert-danger" role="alert">Failed to decode file ( ' + fileName + ' ).</div>';
|
||||
},
|
||||
|
||||
scUrl: computed('playQueuePointer', 'playQueue.[]', 'usingMicAudio', function(){
|
||||
let rtn = null,
|
||||
currentSong = this.get('playQueue')[this.get('playQueuePointer')];
|
||||
|
||||
if(currentSong && currentSong.scUrl && !this.get('usingMicAudio')){
|
||||
rtn = currentSong.scUrl;
|
||||
}
|
||||
|
||||
return rtn;
|
||||
}),
|
||||
|
||||
playQueueEmpty: computed.empty('playQueue'),
|
||||
playQueueNotEmpty: computed.notEmpty('playQueue'),
|
||||
playQueueMultiple: computed('playQueue.[]', function(){
|
||||
return this.get('playQueue').length > 1;
|
||||
}),
|
||||
|
||||
seekPosition: computed('timeElapsed', 'timeTotal', function(){
|
||||
let timeTotal = this.get('timeTotal'),
|
||||
timeElapsed = this.get('timeElapsed');
|
||||
|
||||
if (timeTotal === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return timeElapsed/timeTotal*100;
|
||||
}),
|
||||
|
||||
largeArtworkPic: computed('playQueuePointer', 'usingMicAudio', 'currentVisName', function(){
|
||||
let pic = null,
|
||||
currentVisName = this.get('currentVisName'),
|
||||
usingMicAudio = this.get('usingMicAudio'),
|
||||
playQueuePointer = this.get('playQueuePointer'),
|
||||
playQueue = this.get('playQueue');
|
||||
|
||||
if(playQueuePointer !== -1 && !usingMicAudio && currentVisName === 'None'){
|
||||
var song = playQueue[playQueuePointer];
|
||||
let song = playQueue[playQueuePointer];
|
||||
if(song.scUrl){
|
||||
pic = song.picture.replace('67x67', '500x500');
|
||||
} else {
|
||||
|
|
@ -188,31 +203,29 @@ export default Em.Mixin.create({
|
|||
}
|
||||
|
||||
return pic;
|
||||
}.property('playQueuePointer', 'usingMicAudio', 'currentVisName'),
|
||||
}),
|
||||
|
||||
// used to insure that we don't replay the same thing multiple times in shuffle mode
|
||||
shufflePlayed: [],
|
||||
pauseLightUpdates: function(){
|
||||
pauseLightUpdates: computed('playing', function(){
|
||||
return this.get('playing');
|
||||
}.property('playing'),
|
||||
}),
|
||||
|
||||
micIcon: function () {
|
||||
if (this.get('usingMicAudio')) {
|
||||
micIcon: computed('usingMicAudio', function(){
|
||||
if(this.get('usingMicAudio')) {
|
||||
return 'mic';
|
||||
}
|
||||
|
||||
return 'mic-off';
|
||||
}.property('usingMicAudio'),
|
||||
}),
|
||||
|
||||
repeatIcon: function () {
|
||||
if (this.get('repeat') === 2) {
|
||||
repeatIcon: computed('repeat', function() {
|
||||
if(this.get('repeat') === 2) {
|
||||
return 'repeat-one';
|
||||
}
|
||||
|
||||
return 'repeat';
|
||||
}.property('repeat'),
|
||||
}),
|
||||
|
||||
playingIcon: function () {
|
||||
playingIcon: computed('playing', function() {
|
||||
if(this.get('playing')){
|
||||
return 'pause';
|
||||
} else if(this.get('timeElapsed') === this.get('timeTotal') && this.get('timeTotal') !== 0){
|
||||
|
|
@ -220,10 +233,10 @@ export default Em.Mixin.create({
|
|||
} else {
|
||||
return 'play-arrow';
|
||||
}
|
||||
}.property('playing'),
|
||||
}),
|
||||
|
||||
playListAreaClass: function(){
|
||||
var classes = 'cursorPointer';
|
||||
playListAreaClass: computed('dragging', 'draggingOverPlayListArea', 'dimmerOn', function(){
|
||||
let classes = 'cursorPointer';
|
||||
|
||||
if(this.get('dragging')){
|
||||
classes += ' dragHereHighlight';
|
||||
|
|
@ -238,40 +251,40 @@ export default Em.Mixin.create({
|
|||
}
|
||||
|
||||
return classes;
|
||||
}.property('dragging', 'draggingOverPlayListArea', 'dimmerOn'),
|
||||
}),
|
||||
|
||||
dimmerOnClass: function(){
|
||||
dimmerOnClass: computed('dimmerOn', function(){
|
||||
return this.get('dimmerOn') ? 'dimmerOn' : null;
|
||||
}.property('dimmerOn'),
|
||||
}),
|
||||
|
||||
volumeMutedClass: function(){
|
||||
var classes = 'playerControllIcon volumeButton';
|
||||
volumeMutedClass: computed('volumeMuted', function(){
|
||||
let classes = 'playerControllIcon volumeButton';
|
||||
|
||||
if(this.get('volumeMuted')){
|
||||
classes += ' active';
|
||||
}
|
||||
|
||||
return classes;
|
||||
}.property('volumeMuted'),
|
||||
}),
|
||||
|
||||
usingLocalAudioClass: function() {
|
||||
usingLocalAudioClass: computed('usingLocalAudio', function(){
|
||||
return this.get('usingLocalAudio') ? 'playerControllIcon active' : 'playerControllIcon';
|
||||
}.property('usingLocalAudio'),
|
||||
}),
|
||||
|
||||
usingMicAudioClass: function() {
|
||||
usingMicAudioClass: computed('usingMicAudio', function(){
|
||||
return this.get('usingMicAudio') ? 'playerControllIcon active' : 'playerControllIcon';
|
||||
}.property('usingMicAudio'),
|
||||
}),
|
||||
|
||||
repeatClass: function () {
|
||||
repeatClass: computed('repeat', function(){
|
||||
return this.get('repeat') !== 0 ? 'playerControllIcon active' : 'playerControllIcon';
|
||||
}.property('repeat'),
|
||||
}),
|
||||
|
||||
shuffleClass: function () {
|
||||
shuffleClass: computed('shuffle', function(){
|
||||
return this.get('shuffle') ? 'playerControllIcon active' : 'playerControllIcon';
|
||||
}.property('shuffle'),
|
||||
}),
|
||||
|
||||
volumeIcon: function () {
|
||||
var volume = this.get('volume');
|
||||
volumeIcon: computed('volumeMuted', 'volume', function() {
|
||||
let volume = this.get('volume');
|
||||
|
||||
if (this.get('volumeMuted')) {
|
||||
return "volume-off";
|
||||
|
|
@ -282,21 +295,37 @@ export default Em.Mixin.create({
|
|||
} else {
|
||||
return 'volume-mute';
|
||||
}
|
||||
}.property('volumeMuted', 'volume'),
|
||||
}),
|
||||
|
||||
onColorloopModeChange: function(){
|
||||
var colorLoop = ((this.get('playing') || this.get('usingMicAudio')) && this.get('colorloopMode')) ? true : false;
|
||||
beatDetectionAreaArrowIcon: computed('playerBottomDisplayed', function(){
|
||||
if(!this.get('playerBottomDisplayed')){
|
||||
return 'keyboard-arrow-down';
|
||||
} else {
|
||||
return 'keyboard-arrow-up';
|
||||
}
|
||||
}),
|
||||
|
||||
timeElapsedTxt: computed('timeElapsed', function(){
|
||||
return this.formatTime(this.get('timeElapsed'));
|
||||
}),
|
||||
|
||||
timeTotalTxt: computed('timeTotal', function() {
|
||||
return this.formatTime(this.get('timeTotal'));
|
||||
}),
|
||||
|
||||
onColorloopModeChange: observer('colorloopMode', 'usingMicAudio', 'playing', function(){
|
||||
let colorLoop = ((this.get('playing') || this.get('usingMicAudio')) && this.get('colorloopMode')) ? true : false;
|
||||
|
||||
this.set('colorLoopOn', colorLoop);
|
||||
}.observes('colorloopMode', 'usingMicAudio', 'playing'),
|
||||
}),
|
||||
|
||||
onOptionChange: function(self, option){
|
||||
onOptionChange: observer('flashingTransitions', 'playQueue.[]', 'playQueuePointer', 'colorloopMode', 'ambienceMode', function(self, option){
|
||||
option = option.replace('.[]', '');
|
||||
this.get('storage').set('huegasm.' + option, this.get(option));
|
||||
}.observes('flashingTransitions', 'playQueue.[]', 'playQueuePointer', 'colorloopMode', 'ambienceMode'),
|
||||
}),
|
||||
|
||||
onRepeatChange: function () {
|
||||
var 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';
|
||||
|
|
@ -305,20 +334,20 @@ export default Em.Mixin.create({
|
|||
}
|
||||
|
||||
this.changeTooltipText(type, tooltipTxt);
|
||||
}.observes('repeat').on('init'),
|
||||
})),
|
||||
|
||||
onUsingMicAudioChange: function(){
|
||||
var tooltipTxt = 'Listen to audio through mic', type = 'usingMicAudio';
|
||||
onUsingMicAudioChange: on('init', observer('usingMicAudio', function(){
|
||||
let tooltipTxt = 'Listen to audio through mic', type = 'usingMicAudio';
|
||||
|
||||
if (this.get(type)) {
|
||||
tooltipTxt = 'Listen to audio files';
|
||||
}
|
||||
|
||||
this.changeTooltipText(type, tooltipTxt);
|
||||
}.observes('usingMicAudio').on('init'),
|
||||
})),
|
||||
|
||||
onShuffleChange: function () {
|
||||
var tooltipTxt = 'Shuffle', type = 'shuffle';
|
||||
onShuffleChange: on('init', observer('shuffle', function () {
|
||||
let tooltipTxt = 'Shuffle', type = 'shuffle';
|
||||
|
||||
if (this.get(type)) {
|
||||
this.get('shufflePlayed').clear();
|
||||
|
|
@ -326,10 +355,10 @@ export default Em.Mixin.create({
|
|||
}
|
||||
|
||||
this.changeTooltipText(type, tooltipTxt);
|
||||
}.observes('shuffle').on('init'),
|
||||
})),
|
||||
|
||||
onVolumeMutedChange: function () {
|
||||
var tooltipTxt = 'Mute', type = 'volumeMuted',
|
||||
onVolumeMutedChange: on('init', observer('volumeMuted', function() {
|
||||
let tooltipTxt = 'Mute', type = 'volumeMuted',
|
||||
volumeMuted = this.get(type), dancer = this.get('dancer'),
|
||||
volume=0;
|
||||
|
||||
|
|
@ -345,11 +374,11 @@ export default Em.Mixin.create({
|
|||
}
|
||||
|
||||
this.changeTooltipText(type, tooltipTxt);
|
||||
}.observes('volumeMuted').on('init'),
|
||||
})),
|
||||
|
||||
onPrevChange: function() {
|
||||
onPrevChange: observer('timeElapsed', 'playQueueNotEmpty', 'playQueue.[]', function() {
|
||||
if(this.get('playQueueNotEmpty')){
|
||||
var tooltipTxt = 'Previous', type = 'prev';
|
||||
let tooltipTxt = 'Previous', type = 'prev';
|
||||
|
||||
if(this.get('timeElapsed') > 5 || this.get('playQueue').length === 1) {
|
||||
tooltipTxt = 'Replay';
|
||||
|
|
@ -357,10 +386,10 @@ export default Em.Mixin.create({
|
|||
|
||||
this.changeTooltipText(type, tooltipTxt);
|
||||
}
|
||||
}.observes('timeElapsed', 'playQueueNotEmpty', 'playQueue.[]'),
|
||||
}),
|
||||
|
||||
onPlayingChange: function () {
|
||||
var tooltipTxt = 'Play', type = 'playing';
|
||||
onPlayingChange: on('init', observer('playing', function () {
|
||||
let tooltipTxt = 'Play', type = 'playing';
|
||||
|
||||
if (this.get(type)) {
|
||||
tooltipTxt = 'Pause';
|
||||
|
|
@ -369,35 +398,19 @@ export default Em.Mixin.create({
|
|||
}
|
||||
|
||||
this.changeTooltipText(type, tooltipTxt);
|
||||
}.observes('playing').on('init'),
|
||||
})),
|
||||
|
||||
changeTooltipText(type, text) {
|
||||
// change the tooltip text if it's already visible
|
||||
Em.$('#' + type + 'Tooltip + .tooltip .tooltip-inner').html(text);
|
||||
$('#' + type + 'Tooltip + .tooltip .tooltip-inner').html(text);
|
||||
//change the tooltip text for hover
|
||||
Em.$('#' + type + 'Tooltip').attr('data-original-title', text);
|
||||
$('#' + type + 'Tooltip').attr('data-original-title', text);
|
||||
|
||||
if(Em.isNone(this.get(type + 'TooltipTxt'))) {
|
||||
if(isNone(this.get(type + 'TooltipTxt'))) {
|
||||
this.set(type + 'TooltipTxt', text);
|
||||
}
|
||||
},
|
||||
|
||||
beatDetectionAreaArrowIcon: function(){
|
||||
if(!this.get('playerBottomDisplayed')){
|
||||
return 'keyboard-arrow-down';
|
||||
} else {
|
||||
return 'keyboard-arrow-up';
|
||||
}
|
||||
}.property('playerBottomDisplayed'),
|
||||
|
||||
timeElapsedTxt: function(){
|
||||
return this.formatTime(this.get('timeElapsed'));
|
||||
}.property('timeElapsed'),
|
||||
|
||||
timeTotalTxt: function() {
|
||||
return this.formatTime(this.get('timeTotal'));
|
||||
}.property('timeTotal'),
|
||||
|
||||
formatTime(time){
|
||||
return this.pad(Math.floor(time/60), 2) + ':' + this.pad(time%60, 2);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,27 +1,33 @@
|
|||
import Em from 'ember';
|
||||
import Ember from 'ember';
|
||||
|
||||
export default Em.Mixin.create({
|
||||
const {
|
||||
Mixin,
|
||||
observer,
|
||||
$
|
||||
} = Ember;
|
||||
|
||||
export default Mixin.create({
|
||||
currentVisName: 'None',
|
||||
|
||||
visNames: ['None', 'Bars', 'Wave'],
|
||||
|
||||
onCurrentVisNameChange: function () {
|
||||
var currentVisName = this.get('currentVisName');
|
||||
onCurrentVisNameChange: observer('currentVisName', function () {
|
||||
let currentVisName = this.get('currentVisName');
|
||||
|
||||
if(currentVisName === 'None'){
|
||||
var canvasEl = Em.$('#visualization')[0],
|
||||
let canvasEl = $('#visualization')[0],
|
||||
ctx = canvasEl.getContext('2d');
|
||||
|
||||
ctx.clearRect(0, 0, canvasEl.width, canvasEl.height);
|
||||
}
|
||||
|
||||
this.get('storage').set('huegasm.currentVisName', currentVisName);
|
||||
}.observes('currentVisName'),
|
||||
}),
|
||||
|
||||
didInsertElement(){
|
||||
var dancer = this.get('dancer'),
|
||||
canvas = Em.$('#visualization')[0],
|
||||
playerArea = Em.$('#playerArea'),
|
||||
let dancer = this.get('dancer'),
|
||||
canvas = $('#visualization')[0],
|
||||
playerArea = $('#playerArea'),
|
||||
ctx = canvas.getContext('2d'),
|
||||
spacing = 2,
|
||||
h = playerArea.height(), w;
|
||||
|
|
@ -30,17 +36,17 @@ export default Em.Mixin.create({
|
|||
|
||||
// must be done to preserver resolution so that things don't appear blurry
|
||||
// note that the height is set to 400px via css so it doesn't need to be recalculated
|
||||
var syncCanvasHeight = ()=>{
|
||||
let syncCanvasHeight = ()=>{
|
||||
w = playerArea.width();
|
||||
canvas.width = w;
|
||||
};
|
||||
|
||||
syncCanvasHeight();
|
||||
|
||||
Em.$(window).on('resize', syncCanvasHeight);
|
||||
$(window).on('resize', syncCanvasHeight);
|
||||
|
||||
dancer.bind('update', () => {
|
||||
var currentVisName = this.get('currentVisName'),
|
||||
let currentVisName = this.get('currentVisName'),
|
||||
gradient = ctx.createLinearGradient(0, 0, 0, h),
|
||||
pageHidden = document.hidden || document.msHidden || document.webkitHidden || document.mozHidden;
|
||||
|
||||
|
|
@ -60,7 +66,7 @@ export default Em.Mixin.create({
|
|||
|
||||
ctx.lineWidth = 1;
|
||||
ctx.strokeStyle = gradient;
|
||||
var waveform = dancer.getWaveform();
|
||||
let waveform = dancer.getWaveform();
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(0, h / 2);
|
||||
|
|
@ -78,7 +84,7 @@ export default Em.Mixin.create({
|
|||
gradient.addColorStop(0.2, '#F12B24');
|
||||
|
||||
ctx.fillStyle = gradient;
|
||||
var spectrum = dancer.getSpectrum();
|
||||
let spectrum = dancer.getSpectrum();
|
||||
for (let i = 0, l = spectrum.length; i < l && i < count; i++) {
|
||||
ctx.fillRect(i * ( spacing + width ), h, width, -spectrum[i] * h - 60);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ $secondaryThemeColor: #F12B24;
|
|||
$glowingText: 0 0 2px #fff, 0 0 8px #fff, 0 0 20px #228DFF;
|
||||
$dimmerOnButtonColor: #404040;
|
||||
|
||||
// BRIDGE FINDER
|
||||
// BRIDGE FINDER
|
||||
html {
|
||||
min-height: 100%;
|
||||
height: auto;
|
||||
|
|
|
|||
Reference in a new issue