squashing bugs, tooltip stuff, better drag and dropping
This commit is contained in:
parent
2aeb666226
commit
beab6069f8
9 changed files with 135 additions and 119 deletions
67
README.md
67
README.md
|
|
@ -1,53 +1,24 @@
|
|||
# Huegasm
|
||||
|
||||
This README outlines the details of collaborating on this Ember application.
|
||||
A short introduction of this app could easily go here.
|
||||
Music awesomeness for hue lights.
|
||||
|
||||
## Prerequisites
|
||||
# TODO
|
||||
## FEATURES
|
||||
- finish beat detection light effects
|
||||
- more granular light controls on the lights tab
|
||||
- handle multiple bridge IPs for bridge-finder
|
||||
- save beat detection settings per song
|
||||
- app intro with intro.js
|
||||
- music visualizations with three.js
|
||||
- new favicon
|
||||
|
||||
You will need the following things properly installed on your computer.
|
||||
|
||||
* [Git](http://git-scm.com/)
|
||||
* [Node.js](http://nodejs.org/) (with NPM)
|
||||
* [Bower](http://bower.io/)
|
||||
* [Ember CLI](http://www.ember-cli.com/)
|
||||
* [PhantomJS](http://phantomjs.org/)
|
||||
|
||||
## Installation
|
||||
|
||||
* `git clone <repository-url>` this repository
|
||||
* change into the new directory
|
||||
* `npm install`
|
||||
* `bower install`
|
||||
|
||||
## Running / Development
|
||||
|
||||
* `ember server`
|
||||
* Visit your app at [http://localhost:4200](http://localhost:4200).
|
||||
|
||||
### Code Generators
|
||||
|
||||
Make use of the many generators for code, try `ember help generate` for more details
|
||||
|
||||
### Running Tests
|
||||
|
||||
* `ember test`
|
||||
* `ember test --server`
|
||||
|
||||
### Building
|
||||
|
||||
* `ember build` (development)
|
||||
* `ember build --environment production` (production)
|
||||
|
||||
### Deploying
|
||||
|
||||
Specify what it takes to deploy your app.
|
||||
|
||||
## Further Reading / Useful Links
|
||||
|
||||
* [ember.js](http://emberjs.com/)
|
||||
* [ember-cli](http://www.ember-cli.com/)
|
||||
* Development Browser Extensions
|
||||
* [ember inspector for chrome](https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi)
|
||||
* [ember inspector for firefox](https://addons.mozilla.org/en-US/firefox/addon/ember-inspector/)
|
||||
## POSSIBLE FEATURES
|
||||
- clear localstorage
|
||||
- help, contact, about, youtube video ???
|
||||
- beat settings by interval
|
||||
- integration with youtube, soundcloud, spotify ???
|
||||
|
||||
## BUGS
|
||||
- fuckery when listening to music and switching tabs
|
||||
- can't create groups anymore
|
||||
- BUGS BUGS BUGS
|
||||
|
|
|
|||
|
|
@ -27,16 +27,29 @@ export default Em.Component.extend({
|
|||
}
|
||||
},
|
||||
|
||||
// automatically close the group menu when the user clicks somewhere else
|
||||
click: function() {
|
||||
if(this.get('groupControlDisplayed') && !event.target.classList.contains('menu') && !$(event.target).closest('#groupControls').length) {
|
||||
this.toggleProperty('groupControlDisplayed');
|
||||
}
|
||||
},
|
||||
|
||||
apiURL: function(){
|
||||
return 'http://' + this.get('bridgeIp') + '/api/' + this.get('bridgeUsername');
|
||||
}.property('bridgeIp', 'bridgeUsername'),
|
||||
|
||||
didInsertElement: function(){
|
||||
//TODO: make less shitty
|
||||
// here's a weird way to automatically initialize bootstrap tooltips
|
||||
var observer = new MutationObserver(function(mutations) {
|
||||
Em.run.once(this, function(){
|
||||
Em.$('.bootstrapTooltip').tooltip();
|
||||
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.$('#bridgeControls')[0], {childList: true, subtree: true});
|
||||
},
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@ export default Em.Component.extend({
|
|||
self.set('manualBridgeIpNotFound', true);
|
||||
setTimeout(function(){ self.set('manualBridgeIpNotFound', false); }, 5000);
|
||||
}).then(function () {
|
||||
debugger;
|
||||
self.set('bridgeIp', manualBridgeIp);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@ import Em from 'ember';
|
|||
|
||||
export default Em.Component.extend({
|
||||
classNameBindings: ['groupControlDisplayed:on'],
|
||||
classNames: ['innerControlFrame', 'groupControls'],
|
||||
classNames: ['innerControlFrame'],
|
||||
elementId: 'groupControls',
|
||||
|
||||
tagName: null,
|
||||
|
||||
|
|
|
|||
|
|
@ -64,8 +64,7 @@ export default Em.Component.extend(musicControlMixin, {
|
|||
}
|
||||
},
|
||||
play: function () {
|
||||
var dancer = this.get('dancer'),
|
||||
playQueue = this.get('playQueue');
|
||||
var dancer = this.get('dancer');
|
||||
|
||||
if(this.get('playQueuePointer') !== -1 ) {
|
||||
if (this.get('playing')) {
|
||||
|
|
@ -120,7 +119,6 @@ export default Em.Component.extend(musicControlMixin, {
|
|||
this.get('dancer').source.currentTime = audioPosition;
|
||||
this.set('timeElapsed', audioPosition);
|
||||
},
|
||||
|
||||
volumeMutedChanged: function (value) {
|
||||
var dancer = this.get('dancer'),
|
||||
volumeMuted = Em.isNone(value) ? !this.get('volumeMuted') : value;
|
||||
|
|
@ -196,20 +194,31 @@ export default Em.Component.extend(musicControlMixin, {
|
|||
if (files.hasOwnProperty(key)) {
|
||||
var file = files[key];
|
||||
|
||||
ID3.loadTags("local", updatePlayQueue.bind(file),{
|
||||
dataReader: new FileAPIReader(file)
|
||||
});
|
||||
if(file.type.startsWith('audio')) {
|
||||
ID3.loadTags("local", updatePlayQueue.bind(file),{
|
||||
dataReader: new FileAPIReader(file)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
dragOver: function(){
|
||||
dragLeaveTimeoutHandle: null,
|
||||
|
||||
dragOver: function() {
|
||||
var dragLeaveTimeoutHandle = this.get('dragLeaveTimeoutHandle');
|
||||
this.set('dragging', true);
|
||||
|
||||
if (dragLeaveTimeoutHandle) {
|
||||
clearTimeout(dragLeaveTimeoutHandle);
|
||||
}
|
||||
},
|
||||
|
||||
dragLeave: function(){
|
||||
this.set('dragging', false);
|
||||
// need to delay the dragLeave notification to avoid flickering ( hovering over some page elements causes this event to be sent )
|
||||
var self = this;
|
||||
this.set('dragLeaveTimeoutHandle', setTimeout(function(){ self.set('dragging', false); }, 500));
|
||||
},
|
||||
|
||||
changePlayerControl: function(name, value, isOption){
|
||||
|
|
@ -318,15 +327,17 @@ export default Em.Component.extend(musicControlMixin, {
|
|||
});
|
||||
// control the volume by scrolling up/down
|
||||
Em.$('#playerArea').on('mousewheel', function(event) {
|
||||
var scrollSize = 5;
|
||||
if(self.get('playQueueNotEmpty')) {
|
||||
var scrollSize = 5;
|
||||
|
||||
if(event.deltaY < 0) {
|
||||
scrollSize *= -1;
|
||||
if(event.deltaY < 0) {
|
||||
scrollSize *= -1;
|
||||
}
|
||||
var newVolume = self.get('volume') + scrollSize;
|
||||
|
||||
self.send('volumeChanged', newVolume < 0 ? 0 : newVolume);
|
||||
event.preventDefault();
|
||||
}
|
||||
var newVolume = self.get('volume') + scrollSize;
|
||||
|
||||
self.send('volumeChanged', newVolume < 0 ? 0 : newVolume);
|
||||
event.preventDefault();
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ export default Em.Mixin.create({
|
|||
}.property('playing'),
|
||||
|
||||
playListAreaClass: function(){
|
||||
var classes = 'cursorPointer dragArea';
|
||||
var classes = 'cursorPointer';
|
||||
|
||||
if(this.get('dragging')){
|
||||
classes += ' dragHereHighlight';
|
||||
|
|
@ -199,6 +199,18 @@ export default Em.Mixin.create({
|
|||
this.changeTooltipText(type, tooltipTxt);
|
||||
}.observes('volumeMuted').on('init'),
|
||||
|
||||
onPrevChange: function() {
|
||||
if(this.get('playQueueMultiple')){
|
||||
var tooltipTxt = 'Previous', type = 'prev';
|
||||
|
||||
if(this.get('timeElapsed') > 5) {
|
||||
tooltipTxt = 'Replay';
|
||||
}
|
||||
|
||||
this.changeTooltipText(type, tooltipTxt);
|
||||
}
|
||||
}.observes('timeElapsed', 'playQueueMultiple'),
|
||||
|
||||
onPlayingChange: function () {
|
||||
var tooltipTxt = 'Play', type = 'playing';
|
||||
|
||||
|
|
@ -213,8 +225,11 @@ export default Em.Mixin.create({
|
|||
// change the tooltip text if it's already visible
|
||||
Em.$('#' + type + 'Tooltip + .tooltip .tooltip-inner').html(text);
|
||||
//change the tooltip text for hover
|
||||
Em.$('#' + type + 'Tooltip').attr('data-original-title', text).attr('title', text);
|
||||
this.set(type + 'TooltipTxt', text);
|
||||
Em.$('#' + type + 'Tooltip').attr('data-original-title', text);
|
||||
|
||||
if(Em.isNone(this.get(type + 'TooltipTxt'))) {
|
||||
this.set(type + 'TooltipTxt', text);
|
||||
}
|
||||
},
|
||||
|
||||
timeElapsedTxt: function(){
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ md-progress-circular {
|
|||
overflow: visible;
|
||||
}
|
||||
|
||||
.groupControls {
|
||||
#groupControls {
|
||||
display: none;
|
||||
border-left: 1px solid #C5C5C5;
|
||||
border-bottom: 1px solid #C5C5C5;
|
||||
|
|
@ -140,7 +140,7 @@ md-progress-circular {
|
|||
border-radius: 0 0 5px 5px;
|
||||
}
|
||||
|
||||
.groupControls.on {
|
||||
#groupControls.on {
|
||||
width: 300px;
|
||||
top: 48px;
|
||||
left: -5px;
|
||||
|
|
@ -210,7 +210,7 @@ md-icon.menu {
|
|||
}
|
||||
|
||||
.addButton .group-add:hover {
|
||||
color: darken(#333333, 20%) !important;
|
||||
color: darken(#333333, 5%) !important;
|
||||
}
|
||||
|
||||
.removeButton {
|
||||
|
|
@ -267,7 +267,7 @@ md-toolbar {
|
|||
}
|
||||
|
||||
.close:hover {
|
||||
color: darken(#333333, 20%) !important;
|
||||
color: darken(#333333, 5%) !important;
|
||||
}
|
||||
|
||||
.close:hover {
|
||||
|
|
@ -442,6 +442,7 @@ md-toolbar {
|
|||
height: 333px;
|
||||
margin: 10px auto 0 auto;
|
||||
border-radius: 5px;
|
||||
transition: 0.1s all ease-in-out;
|
||||
#dragHere {
|
||||
position: absolute;
|
||||
top: 41%;
|
||||
|
|
@ -457,6 +458,15 @@ md-toolbar {
|
|||
}
|
||||
}
|
||||
|
||||
#playListArea.dragHereHighlight {
|
||||
background-color: white;
|
||||
border: 5px dotted #5383ff;
|
||||
}
|
||||
#playListArea.draggingOver {
|
||||
background-color: darken(white, 5%);
|
||||
box-shadow: inset 0 0 20px 0 rgba(0,0,0,1);
|
||||
}
|
||||
|
||||
#fileInput {
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
|
|
@ -509,7 +519,7 @@ md-toolbar {
|
|||
|
||||
.beatOption {
|
||||
display: inline-block;
|
||||
margin-left: 0.714em;
|
||||
margin-right: 2em;
|
||||
}
|
||||
|
||||
#playerBottom {
|
||||
|
|
@ -534,15 +544,23 @@ md-toolbar {
|
|||
background-image: url('images/speaker-outer.png');
|
||||
width: 284px;
|
||||
height: 283px;
|
||||
}
|
||||
|
||||
#beatSpeakerCenter {
|
||||
width: 188px;
|
||||
height: 186px;
|
||||
background-image: url('images/speaker-inner.png');
|
||||
position: absolute;
|
||||
top: 16%;
|
||||
left: 18%;
|
||||
#beatSpeakerCenter {
|
||||
width: 188px;
|
||||
height: 186px;
|
||||
background-image: url('images/speaker-inner.png');
|
||||
position: absolute;
|
||||
top: 16%;
|
||||
left: 18%;
|
||||
}
|
||||
#beatSpeakerCenterBackground {
|
||||
width: 188px;
|
||||
height: 186px;
|
||||
background-color: black;
|
||||
position: absolute;
|
||||
top: 16%;
|
||||
left: 18%;
|
||||
z-index: -1;
|
||||
}
|
||||
}
|
||||
|
||||
.pop {
|
||||
|
|
@ -585,13 +603,3 @@ md-toolbar {
|
|||
padding: 10px;
|
||||
box-shadow: 5px 10px 15px 5px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
#playListArea.dragArea.dragHereHighlight {
|
||||
background-color: white;
|
||||
border: 5px dotted #5383ff;
|
||||
}
|
||||
|
||||
#playListArea.dragArea.draggingOver {
|
||||
background-color: darken(white, 5%);
|
||||
box-shadow: inset 0 0 20px 0 rgba(0,0,0,1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,17 +5,13 @@
|
|||
{{range-slider start=seekPosition min=0 max=100 id="seekSlider" slide="seekChanged"}}
|
||||
|
||||
{{#if playQueueMultiple}}
|
||||
<span data-toggle="tooltip" data-placement="top" title="Previous" class="bootstrapTooltip"
|
||||
id="prevTooltip" {{action "previous"}}>{{paper-icon icon="skip-previous" class="playerControllIcon"}}</span><!--
|
||||
<span data-toggle="tooltip" data-placement="top" class="bootstrapTooltip" id="prevTooltip" title={{prevTooltipTxt}} {{action "previous"}}>{{paper-icon icon="skip-previous" class="playerControllIcon"}}</span><!--
|
||||
-->{{/if}}<!--
|
||||
--><span data-toggle="tooltip" data-placement="top"
|
||||
id="playingTooltip" class="bootstrapTooltip" title={{playingTooltipTxt}} {{action "play"}}>{{paper-icon icon=playingIcon class="playerControllIcon"}}</span><!--
|
||||
--><span data-toggle="tooltip" data-placement="top" id="playingTooltip" class="bootstrapTooltip" title={{playingTooltipTxt}} {{action "play"}}>{{paper-icon icon=playingIcon class="playerControllIcon"}}</span><!--
|
||||
-->{{#if playQueueMultiple}}<!--
|
||||
--><span data-toggle="tooltip" data-placement="top" class="bootstrapTooltip"
|
||||
title="Next song" {{action "next"}}>{{paper-icon icon="skip-next" action="" class="playerControllIcon"}}</span><!--
|
||||
--><span data-toggle="tooltip" data-placement="top" class="bootstrapTooltip" title="Next" {{action "next"}}>{{paper-icon icon="skip-next" action="" class="playerControllIcon"}}</span><!--
|
||||
-->{{/if}}<!--
|
||||
--><span data-toggle="tooltip" data-placement="top" class="bootstrapTooltip" id="volumeMutedTooltip"
|
||||
title={{volumeMutedTooltipTxt}} {{action "volumeMutedChanged"}}>{{paper-icon icon=volumeClass class="playerControllIcon volumeButton"}}</span><!--
|
||||
--><span data-toggle="tooltip" data-placement="top" class="bootstrapTooltip" id="volumeMutedTooltip" title={{volumeMutedTooltipTxt}} {{action "volumeMutedChanged"}}>{{paper-icon icon=volumeClass class="playerControllIcon volumeButton"}}</span><!--
|
||||
-->{{range-slider start=volume min=0 max=100 slide="volumeChanged" id="volumeBar"}}
|
||||
|
||||
<span id="playerTimeControls">{{timeElapsedTxt}} / {{timeTotalTxt}}</span>
|
||||
|
|
@ -43,13 +39,13 @@
|
|||
</div>
|
||||
|
||||
<div id="playListArea" class={{playListAreaClass}} {{action "playListAreaAddAudio"}} {{action "playListAreaDragOver" on="dragOver"}} {{action "playListAreaDragLeave" on="dragLeave"}} {{action "dropFiles" on="drop"}}>
|
||||
{{#if playQueueEmpty}}
|
||||
{{#if (or playQueueEmpty dragging)}}
|
||||
<div id="dragHere">Drag your music files here</div>
|
||||
{{paper-icon icon="library-music"}}
|
||||
{{/if}}
|
||||
|
||||
{{#each playQueue as |item index|}}
|
||||
<div class="playlistItem cursorPointer {{if (eq index playQueuePointer) "active"}}" {{action "goToSong" index bubbles=false}}>
|
||||
<div class="playlistItem cursorPointer {{if (eq index playQueuePointer) "active"}} {{if dragging "hidden"}}" {{action "goToSong" index bubbles=false}}>
|
||||
{{#if item.title}}
|
||||
{{item.title}}
|
||||
<div class="songArtist">{{item.artist}}</div>
|
||||
|
|
@ -68,21 +64,22 @@
|
|||
<div id="vertDivider"></div>
|
||||
{{light-group lightsData=lightsData activeLights=activeLights action='clickLight' apiURL=apiURL noHover=true}}
|
||||
|
||||
<span id="beatOptionGroup">
|
||||
<span class="beatOption">
|
||||
{{range-slider start=threshold orientation="vertical" range=beatOptions.threshold.range slide="thresholdChanged" pips=beatOptions.threshold.pips}}
|
||||
Beat Threshold
|
||||
Beat Threshold
|
||||
</span>
|
||||
|
||||
<span class="beatOption">
|
||||
{{range-slider start=decay orientation="vertical" step=beatOptions.decay.step range=beatOptions.decay.range slide="decayChanged" pips=beatOptions.decay.pips}}
|
||||
Beat Decay
|
||||
Beat Decay
|
||||
</span>
|
||||
|
||||
<span class="beatOption">
|
||||
|
||||
{{range-slider start=frequency orientation="vertical" step=beatOptions.frequency.step range=beatOptions.frequency.range connect=true slide="frequencyChanged" pips=beatOptions.frequency.pips}}
|
||||
Beat Frequency Range
|
||||
Beat Frequency Range
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<div id="playerButtonGroup">
|
||||
{{#paper-button raised=true warn=true action="defaultControls"}}Default{{/paper-button}}
|
||||
|
|
@ -90,17 +87,18 @@
|
|||
</span>
|
||||
|
||||
<span id="beatSpeakerContainer" class="col-xs-5">
|
||||
{{#paper-switch checked=speakerViewed noink=true}} {{speakerLabel}} {{/paper-switch}}
|
||||
{{#liquid-if speakerViewed}}
|
||||
{{#paper-switch checked=speakerViewed noink=true}} {{speakerLabel}} {{/paper-switch}}
|
||||
{{#liquid-if speakerViewed}}
|
||||
<div id="beatSpeaker">
|
||||
<span id="beatSpeakerCenter" class="beatSpeakerCenter cursorPointer" {{action "clickSpeaker"}}></span>
|
||||
</div>
|
||||
<span id="beatSpeakerCenterBackground"></span>
|
||||
<span id="beatSpeakerCenter" class="beatSpeakerCenter cursorPointer" {{action "clickSpeaker"}}></span>
|
||||
</div>
|
||||
{{else}}
|
||||
<div id ="beatHistory">
|
||||
{{#each beatHistory as |item|}}
|
||||
<p>{{{item}}}</p>
|
||||
{{/each}}
|
||||
{{#each beatHistory as |item|}}
|
||||
<p>{{{item}}}</p>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/liquid-if}}
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -24,7 +24,7 @@ module.exports = function(environment) {
|
|||
'font-src': "'self' fonts.gstatic.com",
|
||||
'connect-src': "'self' *",
|
||||
'img-src': "'self' data:",
|
||||
'media-src': "'self'",
|
||||
'media-src': "'self' blob:",
|
||||
'style-src': "'self' 'unsafe-inline' fonts.googleapis.com",
|
||||
'object-src': "'self'",
|
||||
'frame-src': "'self'"
|
||||
|
|
|
|||
Reference in a new issue