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:
Egor 2017-02-27 01:12:33 -08:00
parent 3230831d72
commit c7a786b0ca
22 changed files with 162 additions and 207 deletions

View file

@ -3,11 +3,7 @@
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<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'}}
<link href='https://fonts.googleapis.com/css?family=Open+Sans|Raleway' rel='stylesheet' type='text/css'>

View file

@ -31,12 +31,13 @@
</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
trial=trial colorLoopOn=colorLoopOn dimmerOn=dimmerOn playing=playing pauseLightUpdates=pauseLightUpdates}} {{music-tab
active=(eq selectedTab 1) apiURL=apiURL lightsData=lightsData activeLights=activeLights pauseLightUpdates=pauseLightUpdates
trial=trial colorLoopOn=colorLoopOn dimmerOn=dimmerOn playing=playing pauseLightUpdates=pauseLightUpdates}}
{{music-tab active=(eq selectedTab 1) apiURL=apiURL lightsData=lightsData activeLights=activeLights pauseLightUpdates=pauseLightUpdates
dimmerOn=dimmerOn colorLoopOn=colorLoopOn playing=playing action="startIntro"}}
</div>
{{else}}

View file

@ -125,38 +125,40 @@ export default Component.extend({
}
},
lightStartHover(id) {
if (!window.matchMedia || (window.matchMedia("(min-width: 768px)").matches)) {
let hoveredLight = this.get('lightsList').filter(function (light) {
return light.activeClass !== 'unreachable' && light.id === id[0];
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'
});
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) {
if (!window.matchMedia || (window.matchMedia("(min-width: 768px)").matches)) {
let hoveredLight = this.get('lightsList').filter(function (light) {
return light.activeClass !== 'unreachable' && light.id === id[0];
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'
});
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
});
}
}
});

View file

@ -95,7 +95,7 @@ export default Component.extend({
}
},
threshold: 0.3,
threshold: 0.2,
hueRange: [0, 65535],
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, () => {
let value = this.get(name),
self = this;
let value = this.get(name);
this.set(name, value);
@ -137,11 +136,11 @@ export default Component.extend({
if (value) {
chrome.storage.local.get('currentlyListenining', ({currentlyListenining}) => {
if (!currentlyListenining) {
chrome.runtime.sendMessage({ action: 'start-listening' }, function (response) {
chrome.runtime.sendMessage({ action: 'start-listening' }, (response) => {
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 });
}
});

View file

@ -1,6 +1,11 @@
<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"}}"
{{action "toggleListening"}}></a>
{{action "toggleListening"}}>
</a>
</div>
<div class="row {{if dimmerOn "dimmerOn"}}">

View file

@ -58,28 +58,3 @@ div.ember-modal-dialog {
.display-flex {
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;
}

View file

@ -15,13 +15,10 @@
margin: 30px auto 20px;
}
#bridge-finder, .ready-block {
text-align: center;
padding: 10px 15px 0;
font-size: 16px;
}
#bridge-finder {
text-align: center;
padding: 20px;
font-size: 16px;
flex-direction: column;
display: flex;
justify-content: center;

View file

@ -33,7 +33,7 @@
}
#navigation {
padding: 5px 0 2vh;
padding: 5px 0 1vh;
text-align: center;
margin: auto;
position: relative;
@ -95,10 +95,6 @@
font-size: 16px !important;
}
#huegasm-content {
height: 80%;
max-height: 500px;
}
@media(min-width:767px) {
#lights-tab {

View file

@ -1,6 +1,6 @@
.light-group {
max-width: 800px;
margin: 0 auto;
margin: 5px auto;
display: flex;
justify-content: center;
.tooltip.top {

View file

@ -4,12 +4,11 @@
#music-tab {
padding: 0;
margin-top: 20px;
margin-top: 5px;
}
#beat-area {
position: relative;
padding: 0 0 10px;
}
#beat-option-button-group {
@ -17,7 +16,7 @@
}
.beat-option {
padding: 5px 0;
padding: 10px 0;
text-align: center;
md-checkbox {
padding: 10px 0;
@ -30,49 +29,27 @@
font-size: 16px;
justify-content: center;
flex-direction: column;
padding: 10px 0;
padding: 5px 0;
}
button {
margin-top: 0;
}
.tooltip {
margin: 0;
display: inline-block !important;
}
}
#player-bottom {
color: $blackish;
border: 1px solid black;
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;
}
#start-listening {
margin-bottom: 5px;
font-size: 18px;
}
#fancy-button-wrapper {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.fancy-button {
@ -132,12 +109,6 @@
}
}
@media(max-width: 500px) {
.option-description {
height: 55px;
}
}
// mobile overrides
@media(max-width:767px) {
div#player-bottom {

View file

@ -63,7 +63,7 @@ md-switch.md-default-theme.md-checked .md-thumb {
}
md-list-item {
margin-bottom: 1vh;
margin-bottom: 2vh;
}
@media(max-width:500px) {

View file

@ -9,7 +9,7 @@ let isNone = function (obj) {
// the main ember app controls may change these
let state = {
activeLights: [],
threshold: 0.3,
threshold: 0.2,
hueRange: [0, 65535],
brightnessRange: [1, 254],
bridgeIp: null,
@ -113,6 +113,33 @@ chrome.storage.onChanged.addListener(function ({activeLights, threshold, hueRang
chrome.storage.local.set({ currentlyListenining: false });
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) {
if (request.action === 'start-listening') {
chrome.tabCapture.capture({
@ -129,6 +156,12 @@ chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
chrome.storage.local.set({ currentlyListenining: true });
chrome.browserAction.setBadgeText({ text: "♪" });
state.preMusicLightsDataCache = state.lightsData;
stream.getTracks()[0].onended = function () {
chrome.storage.local.set({ isListenining: false });
stopListening();
};
}
sendResponse({ error });
@ -138,28 +171,8 @@ chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
} else if (request.action === 'stop-listening' && stream !== null) {
stream.getTracks()[0].stop();
stream = null;
chrome.browserAction.setBadgeText({ text: "" });
chrome.storage.local.set({ currentlyListenining: false });
let updateLight = function (lightIndex) {
$.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);
}
}
stopListening();
}
return true;
@ -170,7 +183,7 @@ let simulateKick = (/*mag, ratioKickMag*/) => {
chrome.runtime.sendMessage({ action: 'button-bump' });
let color = null,
_stimulateLight = (light, brightness, hue) => {
_stimulateLight = (lightIndex, brightness, hue) => {
let options = { bri: brightness, transitiontime: 1 },
xhr = new XMLHttpRequest();
@ -178,15 +191,13 @@ let simulateKick = (/*mag, ratioKickMag*/) => {
options.hue = hue;
}
if (state.lightsData[light].state.on === false) {
if (state.lightsData[lightIndex].state.on === false) {
options.on = true;
}
$.ajax('http://' + state.bridgeIp + '/api/' + state.bridgeUsername + '/lights/' + light + '/state', {
data: JSON.stringify(options),
contentType: 'application/json',
type: 'PUT'
});
xhr.open('PUT', 'http://' + state.bridgeIp + '/api/' + state.bridgeUsername + '/lights/' + lightIndex + '/state', true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(options));
},
timeToBriOff = 80;

File diff suppressed because one or more lines are too long

View file

@ -3,7 +3,7 @@
"name": "Huegasm for Philips Hue Lights",
"short_name": "Huegasm",
"description": "Manage and synchronize your Philips Hue lights with the beat of your music.",
"version": "1.0.1",
"version": "1.0.2",
"icons": {
"16": "16x16.png",
"48": "48x48.png",
@ -12,7 +12,6 @@
"background": {
"scripts": [
"dancer.js",
"jquery-3.1.1.min.js",
"background.js"
]
},

View file

@ -111,6 +111,12 @@ export default Component.extend({
},
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){
let index = this.get('tabList').indexOf(tabName);
this.set('selectedTab', index);

View file

@ -4,13 +4,23 @@
{{#each tabData as |tab|}}
<span class="navigation-item pointer text-uppercase {{if tab.selected "active"}}" {{action "changeTab" tab.name}}>{{tab.name}}</span>
{{/each}}
{{#paper-menu as |menu|}}
{{#menu.trigger}}
{{#paper-button iconButton=true}}
{{paper-icon "settings-icon" class=dimmerOnClass size=28}}
{{/paper-button}}
{{/menu.trigger}}
{{#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"}}
{{paper-icon "highlight" class=dimmerOnClass}} Dark Mode: <strong>{{if dimmerOn "On" "Off"}}</strong>
{{/content.menu-item}}
@ -35,7 +45,7 @@
</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">
{{lights-tab active=(eq selectedTab 0) apiURL=apiURL lightsData=lightsData activeLights=activeLights syncLight=syncLight trial=trial colorLoopOn=colorLoopOn dimmerOn=dimmerOn playing=playing pauseLightUpdates=pauseLightUpdates}}

View file

@ -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">
© {{year}}
@ -6,11 +10,6 @@
</a>
</div>
<div id="footer-links">
<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">
</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>
<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">
</a>

View file

@ -17,7 +17,7 @@ export default Component.extend({
activeLights: A(),
// 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'),
activeLights = this.get('activeLights'),
dimmerOn = this.get('dimmerOn'),
@ -29,7 +29,7 @@ export default Component.extend({
activeClass = 'light-active';
if (lightsData.hasOwnProperty(key) && lightsData[key].state.reachable) {
switch(lightsData[key].modelid){
switch (lightsData[key].modelid) {
case 'LCT001':
type = 'a19';
break;
@ -61,7 +61,7 @@ export default Component.extend({
type = 'storylight';
break;
case 'LWB004':
type ='a19';
type = 'a19';
break;
case 'LLC020':
type = 'huego';
@ -70,34 +70,34 @@ export default Component.extend({
type = 'a19';
}
if(dimmerOn){
if (dimmerOn) {
type += 'w';
}
if(!activeLights.includes(key)){
if (!activeLights.includes(key)) {
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;
}),
onActiveLightsChange: observer('activeLights.[]', function(){
onActiveLightsChange: observer('activeLights.[]', function () {
this.get('storage').set('huegasm.activeLights', this.get('activeLights'));
}),
init(){
init() {
this._super(...arguments);
let lightsData = this.get('lightsData'),
activeLights = this.get('activeLights'),
activeLightsCache = this.get('storage').get('huegasm.activeLights');
if(!isNone(activeLightsCache)){
activeLightsCache.forEach(function(i){
if (!isNone(activeLightsCache)) {
activeLightsCache.forEach(function (i) {
if (!isNone(lightsData) && lightsData.hasOwnProperty(i) && lightsData[i].state.reachable) {
activeLights.pushObject(i);
}
@ -112,49 +112,55 @@ export default Component.extend({
},
actions: {
clickLight(id){
clickLight(id) {
let activeLights = this.get('activeLights'),
lightId = activeLights.indexOf(id);
if(lightId !== -1){
if (lightId !== -1) {
activeLights.removeObject(id);
} else {
activeLights.pushObject(id);
this.set('syncLight', id);
}
},
lightStartHover(id){
if(!window.matchMedia || (window.matchMedia("(min-width: 768px)").matches)){
let hoveredLight = this.get('lightsList').filter(function(light){
lightStartHover(id) {
if (!window.matchMedia || (window.matchMedia("(min-width: 768px)").matches)) {
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"}),
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){
if(!window.matchMedia || (window.matchMedia("(min-width: 768px)").matches)){
let hoveredLight = this.get('lightsList').filter(function(light){
lightStopHover(id) {
if (!window.matchMedia || (window.matchMedia("(min-width: 768px)").matches)) {
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"}),
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
});
}
}
}

View file

@ -56,7 +56,7 @@ body, button {
#footer-text {
display: inline-block;
font-size: 18px;
padding-left: 39%;
padding-right: 30px;
a {
margin-left: 5px;
}
@ -119,20 +119,6 @@ div.ember-modal-dialog {
}
@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 {
margin-bottom: 10px;
}

View file

@ -1,6 +1,5 @@
#lights-tab {
padding: 0;
margin-top: 5vh;
.paper-icon {
line-height: 0.8 !important;
}
@ -35,7 +34,7 @@
}
#navigation {
padding: 15px 0 4vh;
padding: 15px 0 0;
text-align: center;
margin: auto;
position: relative;

View file

@ -1,6 +1,7 @@
.light-group {
#active-lights {
margin: 2vh auto;
padding-top: 10px;
max-width: 800px;
margin: 0 auto;
display: flex;
justify-content: center;
.tooltip.top {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB