self advertising other huegasm projects on web, no jquery for background chrome, adding missing features and fixing bugs for chrome
This commit is contained in:
parent
3230831d72
commit
c7a786b0ca
22 changed files with 162 additions and 207 deletions
|
|
@ -3,11 +3,7 @@
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<title>Huegasm</title>
|
<title>Huegasm</title>
|
||||||
<meta name="description" content="Huegasm is a free web application for managing and synchronizing your Philips Hue lights with the beat of your music.">
|
|
||||||
<meta name="keywords" content="huegasm,hue,philips hue,lights,ambience,music player">
|
|
||||||
<meta name="author" content="Egor Philippov">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1"> {{content-for 'head'}}
|
<meta name="viewport" content="width=device-width, initial-scale=1"> {{content-for 'head'}}
|
||||||
|
|
||||||
<link href='https://fonts.googleapis.com/css?family=Open+Sans|Raleway' rel='stylesheet' type='text/css'>
|
<link href='https://fonts.googleapis.com/css?family=Open+Sans|Raleway' rel='stylesheet' type='text/css'>
|
||||||
|
|
|
||||||
|
|
@ -31,12 +31,13 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{light-group lightsData=lightsData activeLights=activeLights syncLight=syncLight apiURL=apiURL dimmerOn=dimmerOn lightsIconsOn=lightsIconsOn}}
|
{{light-group lightsData=lightsData activeLights=activeLights syncLight=syncLight apiURL=apiURL dimmerOn=dimmerOn lightsIconsOn=lightsIconsOn pauseLightUpdates=pauseLightUpdates}}
|
||||||
|
|
||||||
<div id="huegasm-content" class="row">
|
<div class="row">
|
||||||
{{lights-tab active=(eq selectedTab 0) apiURL=apiURL lightsData=lightsData activeLights=activeLights syncLight=syncLight
|
{{lights-tab active=(eq selectedTab 0) apiURL=apiURL lightsData=lightsData activeLights=activeLights syncLight=syncLight
|
||||||
trial=trial colorLoopOn=colorLoopOn dimmerOn=dimmerOn playing=playing pauseLightUpdates=pauseLightUpdates}} {{music-tab
|
trial=trial colorLoopOn=colorLoopOn dimmerOn=dimmerOn playing=playing pauseLightUpdates=pauseLightUpdates}}
|
||||||
active=(eq selectedTab 1) apiURL=apiURL lightsData=lightsData activeLights=activeLights pauseLightUpdates=pauseLightUpdates
|
|
||||||
|
{{music-tab active=(eq selectedTab 1) apiURL=apiURL lightsData=lightsData activeLights=activeLights pauseLightUpdates=pauseLightUpdates
|
||||||
dimmerOn=dimmerOn colorLoopOn=colorLoopOn playing=playing action="startIntro"}}
|
dimmerOn=dimmerOn colorLoopOn=colorLoopOn playing=playing action="startIntro"}}
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
|
|
|
||||||
|
|
@ -125,38 +125,40 @@ export default Component.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
lightStartHover(id) {
|
lightStartHover(id) {
|
||||||
if (!window.matchMedia || (window.matchMedia("(min-width: 768px)").matches)) {
|
let hoveredLight = this.get('lightsList').filter(function (light) {
|
||||||
let hoveredLight = this.get('lightsList').filter(function (light) {
|
return light.activeClass !== 'unreachable' && light.id === id[0];
|
||||||
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'
|
||||||
});
|
});
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.setProperties({
|
||||||
|
pauseLightUpdates: true,
|
||||||
|
isHovering: true
|
||||||
|
});
|
||||||
},
|
},
|
||||||
lightStopHover(id) {
|
lightStopHover(id) {
|
||||||
if (!window.matchMedia || (window.matchMedia("(min-width: 768px)").matches)) {
|
let hoveredLight = this.get('lightsList').filter(function (light) {
|
||||||
let hoveredLight = this.get('lightsList').filter(function (light) {
|
return light.activeClass !== 'unreachable' && light.id === id[0];
|
||||||
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'
|
||||||
});
|
});
|
||||||
|
|
||||||
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.setProperties({
|
||||||
|
pauseLightUpdates: false,
|
||||||
|
isHovering: false
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ export default Component.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
threshold: 0.3,
|
threshold: 0.2,
|
||||||
hueRange: [0, 65535],
|
hueRange: [0, 65535],
|
||||||
brightnessRange: [1, 254],
|
brightnessRange: [1, 254],
|
||||||
|
|
||||||
|
|
@ -126,10 +126,9 @@ export default Component.extend({
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
onConfigItemChanged: observer('threshold', 'hueRange', 'brightnessRange', 'isListenining', function (wtf, name) {
|
onConfigItemChanged: observer('threshold', 'hueRange', 'brightnessRange', 'isListenining', function (_class, name) {
|
||||||
once(this, () => {
|
once(this, () => {
|
||||||
let value = this.get(name),
|
let value = this.get(name);
|
||||||
self = this;
|
|
||||||
|
|
||||||
this.set(name, value);
|
this.set(name, value);
|
||||||
|
|
||||||
|
|
@ -137,11 +136,11 @@ export default Component.extend({
|
||||||
if (value) {
|
if (value) {
|
||||||
chrome.storage.local.get('currentlyListenining', ({currentlyListenining}) => {
|
chrome.storage.local.get('currentlyListenining', ({currentlyListenining}) => {
|
||||||
if (!currentlyListenining) {
|
if (!currentlyListenining) {
|
||||||
chrome.runtime.sendMessage({ action: 'start-listening' }, function (response) {
|
chrome.runtime.sendMessage({ action: 'start-listening' }, (response) => {
|
||||||
if (response && response.error) {
|
if (response && response.error) {
|
||||||
self.get('notify').warning({ html: '<div class="alert alert-warning" role="alert">' + response.error + '</div>' });
|
this.get('notify').warning({ html: '<div class="alert alert-warning" role="alert">' + response.error + '</div>' });
|
||||||
|
|
||||||
self.set('isListenining', false);
|
this.set('isListenining', false);
|
||||||
chrome.storage.local.set({ isListenining: false });
|
chrome.storage.local.set({ isListenining: false });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,11 @@
|
||||||
<div id="fancy-button-wrapper">
|
<div id="fancy-button-wrapper">
|
||||||
|
<div id="start-listening" data-toggle="tooltip" data-placement="top" data-title="Toggle to have Huegasm start/stop listening on your active Chrome tab" class="bootstrap-tooltip">
|
||||||
|
{{if isListenining "Stop" "Start"}} Listening
|
||||||
|
</div>
|
||||||
|
|
||||||
<a href="#" data-content="Click here for Huegasm to start listening to your current tab" class="fancy-button note {{if isListenining "active"}}"
|
<a href="#" data-content="Click here for Huegasm to start listening to your current tab" class="fancy-button note {{if isListenining "active"}}"
|
||||||
{{action "toggleListening"}}></a>
|
{{action "toggleListening"}}>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row {{if dimmerOn "dimmerOn"}}">
|
<div class="row {{if dimmerOn "dimmerOn"}}">
|
||||||
|
|
|
||||||
|
|
@ -58,28 +58,3 @@ div.ember-modal-dialog {
|
||||||
.display-flex {
|
.display-flex {
|
||||||
display: flex !important;
|
display: flex !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
// fancy webkit scrollbars
|
|
||||||
::-webkit-scrollbar {
|
|
||||||
-webkit-appearance: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar:vertical {
|
|
||||||
width: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar:horizontal {
|
|
||||||
height: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb {
|
|
||||||
background-color: rgba(0, 0, 0, .5);
|
|
||||||
border-radius: 10px;
|
|
||||||
border: 2px solid #ffffff;
|
|
||||||
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar-track {
|
|
||||||
background-color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,13 +15,10 @@
|
||||||
margin: 30px auto 20px;
|
margin: 30px auto 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#bridge-finder, .ready-block {
|
|
||||||
text-align: center;
|
|
||||||
padding: 10px 15px 0;
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bridge-finder {
|
#bridge-finder {
|
||||||
|
text-align: center;
|
||||||
|
padding: 20px;
|
||||||
|
font-size: 16px;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#navigation {
|
#navigation {
|
||||||
padding: 5px 0 2vh;
|
padding: 5px 0 1vh;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
@ -95,10 +95,6 @@
|
||||||
font-size: 16px !important;
|
font-size: 16px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
#huegasm-content {
|
|
||||||
height: 80%;
|
|
||||||
max-height: 500px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media(min-width:767px) {
|
@media(min-width:767px) {
|
||||||
#lights-tab {
|
#lights-tab {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
.light-group {
|
.light-group {
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
margin: 0 auto;
|
margin: 5px auto;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
.tooltip.top {
|
.tooltip.top {
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,11 @@
|
||||||
|
|
||||||
#music-tab {
|
#music-tab {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin-top: 20px;
|
margin-top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#beat-area {
|
#beat-area {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 0 0 10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#beat-option-button-group {
|
#beat-option-button-group {
|
||||||
|
|
@ -17,7 +16,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.beat-option {
|
.beat-option {
|
||||||
padding: 5px 0;
|
padding: 10px 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
md-checkbox {
|
md-checkbox {
|
||||||
padding: 10px 0;
|
padding: 10px 0;
|
||||||
|
|
@ -30,49 +29,27 @@
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: 10px 0;
|
padding: 5px 0;
|
||||||
}
|
}
|
||||||
button {
|
button {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
.tooltip {
|
.tooltip {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
display: inline-block !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#player-bottom {
|
#start-listening {
|
||||||
color: $blackish;
|
margin-bottom: 5px;
|
||||||
border: 1px solid black;
|
font-size: 18px;
|
||||||
width: 100%;
|
|
||||||
background: white;
|
|
||||||
border-bottom-left-radius: 5px;
|
|
||||||
border-bottom-right-radius: 5px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
#beat-area .light-group {
|
|
||||||
margin: 10px 20px 0 40px;
|
|
||||||
float: right;
|
|
||||||
div {
|
|
||||||
display: block;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.close {
|
|
||||||
font-size: 18px !important;
|
|
||||||
color: rgb(51, 51, 51);
|
|
||||||
display: none;
|
|
||||||
text-shadow: none;
|
|
||||||
&:hover {
|
|
||||||
color: darken(#333333, 5%) !important;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#fancy-button-wrapper {
|
#fancy-button-wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fancy-button {
|
.fancy-button {
|
||||||
|
|
@ -132,12 +109,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media(max-width: 500px) {
|
|
||||||
.option-description {
|
|
||||||
height: 55px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// mobile overrides
|
// mobile overrides
|
||||||
@media(max-width:767px) {
|
@media(max-width:767px) {
|
||||||
div#player-bottom {
|
div#player-bottom {
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ md-switch.md-default-theme.md-checked .md-thumb {
|
||||||
}
|
}
|
||||||
|
|
||||||
md-list-item {
|
md-list-item {
|
||||||
margin-bottom: 1vh;
|
margin-bottom: 2vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media(max-width:500px) {
|
@media(max-width:500px) {
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ let isNone = function (obj) {
|
||||||
// the main ember app controls may change these
|
// the main ember app controls may change these
|
||||||
let state = {
|
let state = {
|
||||||
activeLights: [],
|
activeLights: [],
|
||||||
threshold: 0.3,
|
threshold: 0.2,
|
||||||
hueRange: [0, 65535],
|
hueRange: [0, 65535],
|
||||||
brightnessRange: [1, 254],
|
brightnessRange: [1, 254],
|
||||||
bridgeIp: null,
|
bridgeIp: null,
|
||||||
|
|
@ -113,6 +113,33 @@ chrome.storage.onChanged.addListener(function ({activeLights, threshold, hueRang
|
||||||
chrome.storage.local.set({ currentlyListenining: false });
|
chrome.storage.local.set({ currentlyListenining: false });
|
||||||
chrome.browserAction.setBadgeBackgroundColor({ color: [80, 80, 80, 255] });
|
chrome.browserAction.setBadgeBackgroundColor({ color: [80, 80, 80, 255] });
|
||||||
|
|
||||||
|
let stopListening = function () {
|
||||||
|
chrome.browserAction.setBadgeText({ text: "" });
|
||||||
|
chrome.storage.local.set({ currentlyListenining: false });
|
||||||
|
|
||||||
|
if (state.preMusicLightsDataCache) {
|
||||||
|
let updateLight = function (lightIndex) {
|
||||||
|
let xhr = new XMLHttpRequest();
|
||||||
|
|
||||||
|
xhr.open('PUT', 'http://' + state.bridgeIp + '/api/' + state.bridgeUsername + '/lights/' + lightIndex + '/state', true);
|
||||||
|
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||||
|
xhr.send(JSON.stringify({
|
||||||
|
'on': state.preMusicLightsDataCache[lightIndex].state.on,
|
||||||
|
'hue': state.preMusicLightsDataCache[lightIndex].state.hue,
|
||||||
|
'bri': state.preMusicLightsDataCache[lightIndex].state.bri
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
for (let key in state.lightsData) {
|
||||||
|
if (state.lightsData.hasOwnProperty(key)) {
|
||||||
|
setTimeout(function () {
|
||||||
|
updateLight(key);
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
|
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
|
||||||
if (request.action === 'start-listening') {
|
if (request.action === 'start-listening') {
|
||||||
chrome.tabCapture.capture({
|
chrome.tabCapture.capture({
|
||||||
|
|
@ -129,6 +156,12 @@ chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
|
||||||
chrome.storage.local.set({ currentlyListenining: true });
|
chrome.storage.local.set({ currentlyListenining: true });
|
||||||
chrome.browserAction.setBadgeText({ text: "♪" });
|
chrome.browserAction.setBadgeText({ text: "♪" });
|
||||||
state.preMusicLightsDataCache = state.lightsData;
|
state.preMusicLightsDataCache = state.lightsData;
|
||||||
|
|
||||||
|
stream.getTracks()[0].onended = function () {
|
||||||
|
chrome.storage.local.set({ isListenining: false });
|
||||||
|
|
||||||
|
stopListening();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
sendResponse({ error });
|
sendResponse({ error });
|
||||||
|
|
@ -138,28 +171,8 @@ chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
|
||||||
} else if (request.action === 'stop-listening' && stream !== null) {
|
} else if (request.action === 'stop-listening' && stream !== null) {
|
||||||
stream.getTracks()[0].stop();
|
stream.getTracks()[0].stop();
|
||||||
stream = null;
|
stream = null;
|
||||||
chrome.browserAction.setBadgeText({ text: "" });
|
|
||||||
chrome.storage.local.set({ currentlyListenining: false });
|
|
||||||
|
|
||||||
let updateLight = function (lightIndex) {
|
stopListening();
|
||||||
$.ajax('http://' + state.bridgeIp + '/api/' + state.bridgeUsername + '/lights/' + lightIndex + '/state', {
|
|
||||||
data: JSON.stringify({
|
|
||||||
'on': state.preMusicLightsDataCache[lightIndex].state.on,
|
|
||||||
'hue': state.preMusicLightsDataCache[lightIndex].state.hue,
|
|
||||||
'bri': state.preMusicLightsDataCache[lightIndex].state.bri
|
|
||||||
}),
|
|
||||||
contentType: 'application/json',
|
|
||||||
type: 'PUT'
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
for (let key in state.lightsData) {
|
|
||||||
if (state.lightsData.hasOwnProperty(key)) {
|
|
||||||
setTimeout(function () {
|
|
||||||
updateLight(key);
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -170,7 +183,7 @@ let simulateKick = (/*mag, ratioKickMag*/) => {
|
||||||
chrome.runtime.sendMessage({ action: 'button-bump' });
|
chrome.runtime.sendMessage({ action: 'button-bump' });
|
||||||
|
|
||||||
let color = null,
|
let color = null,
|
||||||
_stimulateLight = (light, brightness, hue) => {
|
_stimulateLight = (lightIndex, brightness, hue) => {
|
||||||
let options = { bri: brightness, transitiontime: 1 },
|
let options = { bri: brightness, transitiontime: 1 },
|
||||||
xhr = new XMLHttpRequest();
|
xhr = new XMLHttpRequest();
|
||||||
|
|
||||||
|
|
@ -178,15 +191,13 @@ let simulateKick = (/*mag, ratioKickMag*/) => {
|
||||||
options.hue = hue;
|
options.hue = hue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.lightsData[light].state.on === false) {
|
if (state.lightsData[lightIndex].state.on === false) {
|
||||||
options.on = true;
|
options.on = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$.ajax('http://' + state.bridgeIp + '/api/' + state.bridgeUsername + '/lights/' + light + '/state', {
|
xhr.open('PUT', 'http://' + state.bridgeIp + '/api/' + state.bridgeUsername + '/lights/' + lightIndex + '/state', true);
|
||||||
data: JSON.stringify(options),
|
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||||
contentType: 'application/json',
|
xhr.send(JSON.stringify(options));
|
||||||
type: 'PUT'
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
timeToBriOff = 80;
|
timeToBriOff = 80;
|
||||||
|
|
||||||
|
|
|
||||||
4
chrome/public/jquery-3.1.1.min.js
vendored
4
chrome/public/jquery-3.1.1.min.js
vendored
File diff suppressed because one or more lines are too long
|
|
@ -3,7 +3,7 @@
|
||||||
"name": "Huegasm for Philips Hue Lights",
|
"name": "Huegasm for Philips Hue Lights",
|
||||||
"short_name": "Huegasm",
|
"short_name": "Huegasm",
|
||||||
"description": "Manage and synchronize your Philips Hue lights with the beat of your music.",
|
"description": "Manage and synchronize your Philips Hue lights with the beat of your music.",
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"icons": {
|
"icons": {
|
||||||
"16": "16x16.png",
|
"16": "16x16.png",
|
||||||
"48": "48x48.png",
|
"48": "48x48.png",
|
||||||
|
|
@ -12,7 +12,6 @@
|
||||||
"background": {
|
"background": {
|
||||||
"scripts": [
|
"scripts": [
|
||||||
"dancer.js",
|
"dancer.js",
|
||||||
"jquery-3.1.1.min.js",
|
|
||||||
"background.js"
|
"background.js"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,12 @@ export default Component.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
|
tryAndroid() {
|
||||||
|
window.open("https://play.google.com/store/apps/details?id=com.hoboman313.huegasm", '_blank');
|
||||||
|
},
|
||||||
|
tryExtension() {
|
||||||
|
window.open("https://chrome.google.com/webstore/detail/huegasm-for-philips-hue-l/mbjanbdhcpohhfecjgbdpcfhnnbofooj", '_blank');
|
||||||
|
},
|
||||||
changeTab(tabName){
|
changeTab(tabName){
|
||||||
let index = this.get('tabList').indexOf(tabName);
|
let index = this.get('tabList').indexOf(tabName);
|
||||||
this.set('selectedTab', index);
|
this.set('selectedTab', index);
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,23 @@
|
||||||
{{#each tabData as |tab|}}
|
{{#each tabData as |tab|}}
|
||||||
<span class="navigation-item pointer text-uppercase {{if tab.selected "active"}}" {{action "changeTab" tab.name}}>{{tab.name}}</span>
|
<span class="navigation-item pointer text-uppercase {{if tab.selected "active"}}" {{action "changeTab" tab.name}}>{{tab.name}}</span>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
||||||
{{#paper-menu as |menu|}}
|
{{#paper-menu as |menu|}}
|
||||||
{{#menu.trigger}}
|
{{#menu.trigger}}
|
||||||
{{#paper-button iconButton=true}}
|
{{#paper-button iconButton=true}}
|
||||||
{{paper-icon "settings-icon" class=dimmerOnClass size=28}}
|
{{paper-icon "settings-icon" class=dimmerOnClass size=28}}
|
||||||
{{/paper-button}}
|
{{/paper-button}}
|
||||||
{{/menu.trigger}}
|
{{/menu.trigger}}
|
||||||
|
|
||||||
{{#menu.content width=3 as |content|}}
|
{{#menu.content width=3 as |content|}}
|
||||||
|
{{#content.menu-item class="hidden-xs" onClick="tryExtension"}}
|
||||||
|
{{paper-icon "extension" class=dimmerOnClass}} Try the Chrome Extension
|
||||||
|
{{/content.menu-item}}
|
||||||
|
|
||||||
|
{{#content.menu-item class="visible-xs" onClick="tryAndroid"}}
|
||||||
|
{{paper-icon "extension" class=dimmerOnClass}} Try the Android Extension
|
||||||
|
{{/content.menu-item}}
|
||||||
|
|
||||||
{{#content.menu-item onClick="toggleDimmer"}}
|
{{#content.menu-item onClick="toggleDimmer"}}
|
||||||
{{paper-icon "highlight" class=dimmerOnClass}} Dark Mode: <strong>{{if dimmerOn "On" "Off"}}</strong>
|
{{paper-icon "highlight" class=dimmerOnClass}} Dark Mode: <strong>{{if dimmerOn "On" "Off"}}</strong>
|
||||||
{{/content.menu-item}}
|
{{/content.menu-item}}
|
||||||
|
|
@ -35,7 +45,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{light-group lightsData=lightsData activeLights=activeLights syncLight=syncLight apiURL=apiURL dimmerOn=dimmerOn lightsIconsOn=lightsIconsOn storage=storage}}
|
{{light-group lightsData=lightsData activeLights=activeLights syncLight=syncLight apiURL=apiURL dimmerOn=dimmerOn lightsIconsOn=lightsIconsOn storage=storage pauseLightUpdates=pauseLightUpdates}}
|
||||||
|
|
||||||
<div id="huegasm-content" class="row">
|
<div id="huegasm-content" class="row">
|
||||||
{{lights-tab active=(eq selectedTab 0) apiURL=apiURL lightsData=lightsData activeLights=activeLights syncLight=syncLight trial=trial colorLoopOn=colorLoopOn dimmerOn=dimmerOn playing=playing pauseLightUpdates=pauseLightUpdates}}
|
{{lights-tab active=(eq selectedTab 0) apiURL=apiURL lightsData=lightsData activeLights=activeLights syncLight=syncLight trial=trial colorLoopOn=colorLoopOn dimmerOn=dimmerOn playing=playing pauseLightUpdates=pauseLightUpdates}}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,7 @@
|
||||||
|
<a href="https://chrome.google.com/webstore/detail/huegasm-for-philips-hue-l/mbjanbdhcpohhfecjgbdpcfhnnbofooj" target="_blank" rel="noopener noreferrer" class="hidden-xs">
|
||||||
|
<img src="assets/images/chrome-store-badge.png" alt="Available in the Chrome Web Store">
|
||||||
|
</a>
|
||||||
|
|
||||||
<div id="footer-text">
|
<div id="footer-text">
|
||||||
© {{year}}
|
© {{year}}
|
||||||
|
|
||||||
|
|
@ -6,11 +10,6 @@
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="footer-links">
|
<a href="https://play.google.com/store/apps/details?id=com.hoboman313.huegasm" target="_blank" rel="noopener noreferrer">
|
||||||
<a href="https://play.google.com/store/apps/details?id=com.hoboman313.huegasm" target="_blank" rel="noopener noreferrer">
|
<img src="assets/images/google-play-badge.png" alt="Get it on the Google Play Store">
|
||||||
<img src="assets/images/google-play-badge.png" alt="Get it on the Google Play Store">
|
</a>
|
||||||
</a>
|
|
||||||
<a href="https://chrome.google.com/webstore/detail/huegasm-for-philips-hue-l/mbjanbdhcpohhfecjgbdpcfhnnbofooj" target="_blank" rel="noopener noreferrer">
|
|
||||||
<img src="assets/images/chrome-store-badge.png" alt="Available in the Chrome Web Store">
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
@ -17,7 +17,7 @@ export default Component.extend({
|
||||||
activeLights: A(),
|
activeLights: A(),
|
||||||
|
|
||||||
// list of all the lights in the hue system
|
// list of all the lights in the hue system
|
||||||
lightsList: computed('lightsData', 'activeLights.[]', 'dimmerOn', function(){
|
lightsList: computed('lightsData', 'activeLights.[]', 'dimmerOn', function () {
|
||||||
let lightsData = this.get('lightsData'),
|
let lightsData = this.get('lightsData'),
|
||||||
activeLights = this.get('activeLights'),
|
activeLights = this.get('activeLights'),
|
||||||
dimmerOn = this.get('dimmerOn'),
|
dimmerOn = this.get('dimmerOn'),
|
||||||
|
|
@ -29,7 +29,7 @@ export default Component.extend({
|
||||||
activeClass = 'light-active';
|
activeClass = 'light-active';
|
||||||
|
|
||||||
if (lightsData.hasOwnProperty(key) && lightsData[key].state.reachable) {
|
if (lightsData.hasOwnProperty(key) && lightsData[key].state.reachable) {
|
||||||
switch(lightsData[key].modelid){
|
switch (lightsData[key].modelid) {
|
||||||
case 'LCT001':
|
case 'LCT001':
|
||||||
type = 'a19';
|
type = 'a19';
|
||||||
break;
|
break;
|
||||||
|
|
@ -61,7 +61,7 @@ export default Component.extend({
|
||||||
type = 'storylight';
|
type = 'storylight';
|
||||||
break;
|
break;
|
||||||
case 'LWB004':
|
case 'LWB004':
|
||||||
type ='a19';
|
type = 'a19';
|
||||||
break;
|
break;
|
||||||
case 'LLC020':
|
case 'LLC020':
|
||||||
type = 'huego';
|
type = 'huego';
|
||||||
|
|
@ -70,34 +70,34 @@ export default Component.extend({
|
||||||
type = 'a19';
|
type = 'a19';
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dimmerOn){
|
if (dimmerOn) {
|
||||||
type += 'w';
|
type += 'w';
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!activeLights.includes(key)){
|
if (!activeLights.includes(key)) {
|
||||||
activeClass = 'light-inactive';
|
activeClass = 'light-inactive';
|
||||||
}
|
}
|
||||||
|
|
||||||
lightsList.push({type: type, name: lightsData[key].name, id: key, data: lightsData[key], activeClass: activeClass});
|
lightsList.push({ type: type, name: lightsData[key].name, id: key, data: lightsData[key], activeClass: activeClass });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return lightsList;
|
return lightsList;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
onActiveLightsChange: observer('activeLights.[]', function(){
|
onActiveLightsChange: observer('activeLights.[]', function () {
|
||||||
this.get('storage').set('huegasm.activeLights', this.get('activeLights'));
|
this.get('storage').set('huegasm.activeLights', this.get('activeLights'));
|
||||||
}),
|
}),
|
||||||
|
|
||||||
init(){
|
init() {
|
||||||
this._super(...arguments);
|
this._super(...arguments);
|
||||||
|
|
||||||
let lightsData = this.get('lightsData'),
|
let lightsData = this.get('lightsData'),
|
||||||
activeLights = this.get('activeLights'),
|
activeLights = this.get('activeLights'),
|
||||||
activeLightsCache = this.get('storage').get('huegasm.activeLights');
|
activeLightsCache = this.get('storage').get('huegasm.activeLights');
|
||||||
|
|
||||||
if(!isNone(activeLightsCache)){
|
if (!isNone(activeLightsCache)) {
|
||||||
activeLightsCache.forEach(function(i){
|
activeLightsCache.forEach(function (i) {
|
||||||
if (!isNone(lightsData) && lightsData.hasOwnProperty(i) && lightsData[i].state.reachable) {
|
if (!isNone(lightsData) && lightsData.hasOwnProperty(i) && lightsData[i].state.reachable) {
|
||||||
activeLights.pushObject(i);
|
activeLights.pushObject(i);
|
||||||
}
|
}
|
||||||
|
|
@ -112,49 +112,55 @@ export default Component.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
clickLight(id){
|
clickLight(id) {
|
||||||
let activeLights = this.get('activeLights'),
|
let activeLights = this.get('activeLights'),
|
||||||
lightId = activeLights.indexOf(id);
|
lightId = activeLights.indexOf(id);
|
||||||
|
|
||||||
if(lightId !== -1){
|
if (lightId !== -1) {
|
||||||
activeLights.removeObject(id);
|
activeLights.removeObject(id);
|
||||||
} else {
|
} else {
|
||||||
activeLights.pushObject(id);
|
activeLights.pushObject(id);
|
||||||
this.set('syncLight', id);
|
this.set('syncLight', id);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
lightStartHover(id){
|
lightStartHover(id) {
|
||||||
if(!window.matchMedia || (window.matchMedia("(min-width: 768px)").matches)){
|
if (!window.matchMedia || (window.matchMedia("(min-width: 768px)").matches)) {
|
||||||
let hoveredLight = this.get('lightsList').filter(function(light){
|
let hoveredLight = this.get('lightsList').filter(function (light) {
|
||||||
return light.activeClass !== 'unreachable' && light.id === id[0];
|
return light.activeClass !== 'unreachable' && light.id === id[0];
|
||||||
});
|
});
|
||||||
|
|
||||||
if(!isEmpty(hoveredLight) && this.get('noHover') !== true){
|
if (!isEmpty(hoveredLight) && this.get('noHover') !== true) {
|
||||||
$.ajax(this.get('apiURL') + '/lights/' + id + '/state', {
|
$.ajax(this.get('apiURL') + '/lights/' + id + '/state', {
|
||||||
data: JSON.stringify({"alert": "lselect"}),
|
data: JSON.stringify({ "alert": "lselect" }),
|
||||||
contentType: 'application/json',
|
contentType: 'application/json',
|
||||||
type: 'PUT'
|
type: 'PUT'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.set('isHovering', true);
|
this.setProperties({
|
||||||
|
pauseLightUpdates: true,
|
||||||
|
isHovering: true
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
lightStopHover(id){
|
lightStopHover(id) {
|
||||||
if(!window.matchMedia || (window.matchMedia("(min-width: 768px)").matches)){
|
if (!window.matchMedia || (window.matchMedia("(min-width: 768px)").matches)) {
|
||||||
let hoveredLight = this.get('lightsList').filter(function(light){
|
let hoveredLight = this.get('lightsList').filter(function (light) {
|
||||||
return light.activeClass !== 'unreachable' && light.id === id[0];
|
return light.activeClass !== 'unreachable' && light.id === id[0];
|
||||||
});
|
});
|
||||||
|
|
||||||
if(!isEmpty(hoveredLight) && this.get('noHover') !== true){
|
if (!isEmpty(hoveredLight) && this.get('noHover') !== true) {
|
||||||
$.ajax(this.get('apiURL') + '/lights/' + id + '/state', {
|
$.ajax(this.get('apiURL') + '/lights/' + id + '/state', {
|
||||||
data: JSON.stringify({"alert": "none"}),
|
data: JSON.stringify({ "alert": "none" }),
|
||||||
contentType: 'application/json',
|
contentType: 'application/json',
|
||||||
type: 'PUT'
|
type: 'PUT'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.set('isHovering', false);
|
this.setProperties({
|
||||||
|
pauseLightUpdates: false,
|
||||||
|
isHovering: false
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ body, button {
|
||||||
#footer-text {
|
#footer-text {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
padding-left: 39%;
|
padding-right: 30px;
|
||||||
a {
|
a {
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
@ -119,20 +119,6 @@ div.ember-modal-dialog {
|
||||||
}
|
}
|
||||||
|
|
||||||
@media(max-width:768px) {
|
@media(max-width:768px) {
|
||||||
#footer {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
#footer-links {
|
|
||||||
margin-top: 10px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-around;
|
|
||||||
}
|
|
||||||
|
|
||||||
#footer-text {
|
|
||||||
padding-left: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
#intro-logo {
|
#intro-logo {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
#lights-tab {
|
#lights-tab {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin-top: 5vh;
|
|
||||||
.paper-icon {
|
.paper-icon {
|
||||||
line-height: 0.8 !important;
|
line-height: 0.8 !important;
|
||||||
}
|
}
|
||||||
|
|
@ -35,7 +34,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#navigation {
|
#navigation {
|
||||||
padding: 15px 0 4vh;
|
padding: 15px 0 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
.light-group {
|
#active-lights {
|
||||||
|
margin: 2vh auto;
|
||||||
|
padding-top: 10px;
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
margin: 0 auto;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
.tooltip.top {
|
.tooltip.top {
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 4.5 KiB |
Reference in a new issue